From 2b06170730b88f91254cb71445bb9dbc28e937e0 Mon Sep 17 00:00:00 2001 From: robo-bo Date: Thu, 1 Sep 2022 20:45:24 +0300 Subject: [PATCH] Start to go to fast api (with backward compatibility) --- Agent/start-daemon.cmd | 3 +- Agent/start.cmd | 3 +- Orchestrator/start.cmd | 3 +- .../anyio-3.6.1.dist-info/INSTALLER | 1 + .../anyio-3.6.1.dist-info/LICENSE | 20 + .../anyio-3.6.1.dist-info/METADATA | 102 + .../anyio-3.6.1.dist-info/RECORD | 82 + .../site-packages/anyio-3.6.1.dist-info/WHEEL | 5 + .../anyio-3.6.1.dist-info/entry_points.txt | 2 + .../anyio-3.6.1.dist-info/top_level.txt | 1 + .../Lib/site-packages/anyio/__init__.py | 167 + .../site-packages/anyio/_backends/__init__.py | 0 .../site-packages/anyio/_backends/_asyncio.py | 2181 ++++ .../site-packages/anyio/_backends/_trio.py | 988 ++ .../Lib/site-packages/anyio/_core/__init__.py | 0 .../Lib/site-packages/anyio/_core/_compat.py | 218 + .../site-packages/anyio/_core/_eventloop.py | 155 + .../site-packages/anyio/_core/_exceptions.py | 93 + .../Lib/site-packages/anyio/_core/_fileio.py | 607 + .../site-packages/anyio/_core/_resources.py | 16 + .../Lib/site-packages/anyio/_core/_signals.py | 24 + .../Lib/site-packages/anyio/_core/_sockets.py | 587 + .../Lib/site-packages/anyio/_core/_streams.py | 45 + .../anyio/_core/_subprocesses.py | 136 + .../anyio/_core/_synchronization.py | 595 + .../Lib/site-packages/anyio/_core/_tasks.py | 178 + .../Lib/site-packages/anyio/_core/_testing.py | 80 + .../site-packages/anyio/_core/_typedattr.py | 81 + .../Lib/site-packages/anyio/abc/__init__.py | 88 + .../Lib/site-packages/anyio/abc/_resources.py | 29 + .../Lib/site-packages/anyio/abc/_sockets.py | 183 + .../Lib/site-packages/anyio/abc/_streams.py | 198 + .../site-packages/anyio/abc/_subprocesses.py | 78 + .../Lib/site-packages/anyio/abc/_tasks.py | 104 + .../Lib/site-packages/anyio/abc/_testing.py | 68 + .../Lib/site-packages/anyio/from_thread.py | 502 + .../Lib/site-packages/anyio/lowlevel.py | 170 + .../Lib/site-packages/anyio/py.typed | 0 .../Lib/site-packages/anyio/pytest_plugin.py | 144 + .../site-packages/anyio/streams/__init__.py | 0 .../site-packages/anyio/streams/buffered.py | 116 + .../Lib/site-packages/anyio/streams/file.py | 145 + .../Lib/site-packages/anyio/streams/memory.py | 275 + .../site-packages/anyio/streams/stapled.py | 138 + .../Lib/site-packages/anyio/streams/text.py | 141 + .../Lib/site-packages/anyio/streams/tls.py | 317 + .../Lib/site-packages/anyio/to_process.py | 247 + .../Lib/site-packages/anyio/to_thread.py | 65 + .../click-8.1.3.dist-info/INSTALLER | 1 + .../click-8.1.3.dist-info/LICENSE.rst | 28 + .../click-8.1.3.dist-info/METADATA | 111 + .../click-8.1.3.dist-info/RECORD | 39 + .../site-packages/click-8.1.3.dist-info/WHEEL | 5 + .../click-8.1.3.dist-info/top_level.txt | 1 + .../Lib/site-packages/click/__init__.py | 73 + .../Lib/site-packages/click/_compat.py | 626 + .../Lib/site-packages/click/_termui_impl.py | 717 ++ .../Lib/site-packages/click/_textwrap.py | 49 + .../Lib/site-packages/click/_winconsole.py | 279 + .../Lib/site-packages/click/core.py | 2998 +++++ .../Lib/site-packages/click/decorators.py | 497 + .../Lib/site-packages/click/exceptions.py | 287 + .../Lib/site-packages/click/formatting.py | 301 + .../Lib/site-packages/click/globals.py | 68 + .../Lib/site-packages/click/parser.py | 529 + .../Lib/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 580 + .../Lib/site-packages/click/termui.py | 787 ++ .../Lib/site-packages/click/testing.py | 479 + .../Lib/site-packages/click/types.py | 1073 ++ .../Lib/site-packages/click/utils.py | 580 + .../Lib/site-packages/dotenv/__init__.py | 49 + .../Lib/site-packages/dotenv/cli.py | 164 + .../Lib/site-packages/dotenv/ipython.py | 39 + .../Lib/site-packages/dotenv/main.py | 373 + .../Lib/site-packages/dotenv/parser.py | 182 + .../Lib/site-packages/dotenv/py.typed | 1 + .../Lib/site-packages/dotenv/variables.py | 88 + .../Lib/site-packages/dotenv/version.py | 1 + .../fastapi-0.81.0.dist-info/INSTALLER | 1 + .../fastapi-0.81.0.dist-info/LICENSE | 21 + .../fastapi-0.81.0.dist-info/METADATA | 551 + .../fastapi-0.81.0.dist-info/RECORD | 91 + .../fastapi-0.81.0.dist-info/REQUESTED | 0 .../fastapi-0.81.0.dist-info/WHEEL | 4 + .../Lib/site-packages/fastapi/__init__.py | 24 + .../Lib/site-packages/fastapi/applications.py | 871 ++ .../Lib/site-packages/fastapi/background.py | 1 + .../Lib/site-packages/fastapi/concurrency.py | 32 + .../site-packages/fastapi/datastructures.py | 56 + .../fastapi/dependencies/__init__.py | 0 .../fastapi/dependencies/models.py | 58 + .../fastapi/dependencies/utils.py | 756 ++ .../Lib/site-packages/fastapi/encoders.py | 167 + .../fastapi/exception_handlers.py | 25 + .../Lib/site-packages/fastapi/exceptions.py | 36 + .../Lib/site-packages/fastapi/logger.py | 3 + .../fastapi/middleware/__init__.py | 1 + .../fastapi/middleware/asyncexitstack.py | 28 + .../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 .../fastapi/openapi/constants.py | 2 + .../Lib/site-packages/fastapi/openapi/docs.py | 203 + .../site-packages/fastapi/openapi/models.py | 406 + .../site-packages/fastapi/openapi/utils.py | 441 + .../site-packages/fastapi/param_functions.py | 290 + .../Lib/site-packages/fastapi/params.py | 380 + .../Lib/site-packages/fastapi/py.typed | 0 .../Lib/site-packages/fastapi/requests.py | 2 + .../Lib/site-packages/fastapi/responses.py | 34 + .../Lib/site-packages/fastapi/routing.py | 1237 ++ .../fastapi/security/__init__.py | 15 + .../site-packages/fastapi/security/api_key.py | 92 + .../site-packages/fastapi/security/base.py | 6 + .../site-packages/fastapi/security/http.py | 165 + .../site-packages/fastapi/security/oauth2.py | 220 + .../fastapi/security/open_id_connect_url.py | 34 + .../site-packages/fastapi/security/utils.py | 8 + .../Lib/site-packages/fastapi/staticfiles.py | 1 + .../Lib/site-packages/fastapi/templating.py | 1 + .../Lib/site-packages/fastapi/testclient.py | 1 + .../Lib/site-packages/fastapi/types.py | 3 + .../Lib/site-packages/fastapi/utils.py | 189 + .../Lib/site-packages/fastapi/websockets.py | 2 + .../h11-0.13.0.dist-info/INSTALLER | 1 + .../h11-0.13.0.dist-info/LICENSE.txt | 22 + .../h11-0.13.0.dist-info/METADATA | 197 + .../site-packages/h11-0.13.0.dist-info/RECORD | 52 + .../site-packages/h11-0.13.0.dist-info/WHEEL | 5 + .../h11-0.13.0.dist-info/top_level.txt | 1 + .../Lib/site-packages/h11/__init__.py | 62 + .../Lib/site-packages/h11/_abnf.py | 129 + .../Lib/site-packages/h11/_connection.py | 631 + .../Lib/site-packages/h11/_events.py | 369 + .../Lib/site-packages/h11/_headers.py | 278 + .../Lib/site-packages/h11/_readers.py | 249 + .../Lib/site-packages/h11/_receivebuffer.py | 153 + .../Lib/site-packages/h11/_state.py | 363 + .../Lib/site-packages/h11/_util.py | 135 + .../Lib/site-packages/h11/_version.py | 16 + .../Lib/site-packages/h11/_writers.py | 145 + .../Lib/site-packages/h11/py.typed | 1 + .../Lib/site-packages/h11/tests/__init__.py | 0 .../site-packages/h11/tests/data/test-file | 1 + .../Lib/site-packages/h11/tests/helpers.py | 101 + .../h11/tests/test_against_stdlib_http.py | 115 + .../h11/tests/test_connection.py | 1122 ++ .../site-packages/h11/tests/test_events.py | 150 + .../site-packages/h11/tests/test_headers.py | 157 + .../site-packages/h11/tests/test_helpers.py | 32 + .../Lib/site-packages/h11/tests/test_io.py | 566 + .../h11/tests/test_receivebuffer.py | 135 + .../Lib/site-packages/h11/tests/test_state.py | 271 + .../Lib/site-packages/h11/tests/test_util.py | 112 + .../httptools-0.4.0.dist-info/INSTALLER | 1 + .../httptools-0.4.0.dist-info/LICENSE | 21 + .../httptools-0.4.0.dist-info/METADATA | 135 + .../httptools-0.4.0.dist-info/RECORD | 18 + .../httptools-0.4.0.dist-info/WHEEL | 5 + .../httptools-0.4.0.dist-info/top_level.txt | 1 + .../Lib/site-packages/httptools/__init__.py | 6 + .../Lib/site-packages/httptools/_version.py | 13 + .../httptools/parser/__init__.py | 5 + .../site-packages/httptools/parser/errors.py | 30 + .../site-packages/httptools/parser/parser.c | 10421 ++++++++++++++++ .../parser/parser.cp37-win_amd64.pyd | Bin 0 -> 83968 bytes .../httptools/parser/url_parser.c | 6031 +++++++++ .../parser/url_parser.cp37-win_amd64.pyd | Bin 0 -> 39424 bytes .../pydantic-1.10.1.dist-info/INSTALLER | 1 + .../pydantic-1.10.1.dist-info/LICENSE | 21 + .../pydantic-1.10.1.dist-info/METADATA | 1221 ++ .../pydantic-1.10.1.dist-info/RECORD | 85 + .../pydantic-1.10.1.dist-info/WHEEL | 5 + .../entry_points.txt | 2 + .../pydantic-1.10.1.dist-info/top_level.txt | 1 + .../pydantic/__init__.cp37-win_amd64.pyd | Bin 0 -> 34304 bytes .../Lib/site-packages/pydantic/__init__.py | 131 + .../_hypothesis_plugin.cp37-win_amd64.pyd | Bin 0 -> 154112 bytes .../pydantic/_hypothesis_plugin.py | 386 + .../annotated_types.cp37-win_amd64.pyd | Bin 0 -> 67072 bytes .../site-packages/pydantic/annotated_types.py | 72 + .../class_validators.cp37-win_amd64.pyd | Bin 0 -> 183296 bytes .../pydantic/class_validators.py | 342 + .../pydantic/color.cp37-win_amd64.pyd | Bin 0 -> 224256 bytes .../Lib/site-packages/pydantic/color.py | 494 + .../pydantic/config.cp37-win_amd64.pyd | Bin 0 -> 79360 bytes .../Lib/site-packages/pydantic/config.py | 192 + .../pydantic/dataclasses.cp37-win_amd64.pyd | Bin 0 -> 177152 bytes .../Lib/site-packages/pydantic/dataclasses.py | 458 + .../datetime_parse.cp37-win_amd64.pyd | Bin 0 -> 96256 bytes .../site-packages/pydantic/datetime_parse.py | 248 + .../pydantic/decorator.cp37-win_amd64.pyd | Bin 0 -> 134144 bytes .../Lib/site-packages/pydantic/decorator.py | 264 + .../pydantic/env_settings.cp37-win_amd64.pyd | Bin 0 -> 169472 bytes .../site-packages/pydantic/env_settings.py | 346 + .../error_wrappers.cp37-win_amd64.pyd | Bin 0 -> 117248 bytes .../site-packages/pydantic/error_wrappers.py | 162 + .../pydantic/errors.cp37-win_amd64.pyd | Bin 0 -> 184320 bytes .../Lib/site-packages/pydantic/errors.py | 646 + .../pydantic/fields.cp37-win_amd64.pyd | Bin 0 -> 391168 bytes .../Lib/site-packages/pydantic/fields.py | 1247 ++ .../Lib/site-packages/pydantic/generics.py | 360 + .../pydantic/json.cp37-win_amd64.pyd | Bin 0 -> 69632 bytes .../Lib/site-packages/pydantic/json.py | 112 + .../pydantic/main.cp37-win_amd64.pyd | Bin 0 -> 385024 bytes .../Lib/site-packages/pydantic/main.py | 1109 ++ .../pydantic/mypy.cp37-win_amd64.pyd | Bin 0 -> 318464 bytes .../Lib/site-packages/pydantic/mypy.py | 837 ++ .../pydantic/networks.cp37-win_amd64.pyd | Bin 0 -> 256512 bytes .../Lib/site-packages/pydantic/networks.py | 745 ++ .../pydantic/parse.cp37-win_amd64.pyd | Bin 0 -> 50176 bytes .../Lib/site-packages/pydantic/parse.py | 66 + .../Lib/site-packages/pydantic/py.typed | 0 .../pydantic/schema.cp37-win_amd64.pyd | Bin 0 -> 346624 bytes .../Lib/site-packages/pydantic/schema.py | 1153 ++ .../pydantic/tools.cp37-win_amd64.pyd | Bin 0 -> 64000 bytes .../Lib/site-packages/pydantic/tools.py | 92 + .../pydantic/types.cp37-win_amd64.pyd | Bin 0 -> 354816 bytes .../Lib/site-packages/pydantic/types.py | 1187 ++ .../pydantic/typing.cp37-win_amd64.pyd | Bin 0 -> 200704 bytes .../Lib/site-packages/pydantic/typing.py | 602 + .../pydantic/utils.cp37-win_amd64.pyd | Bin 0 -> 305152 bytes .../Lib/site-packages/pydantic/utils.py | 841 ++ .../pydantic/validators.cp37-win_amd64.pyd | Bin 0 -> 264704 bytes .../Lib/site-packages/pydantic/validators.py | 752 ++ .../pydantic/version.cp37-win_amd64.pyd | Bin 0 -> 53760 bytes .../Lib/site-packages/pydantic/version.py | 38 + .../python_dotenv-0.20.0.dist-info/INSTALLER | 1 + .../python_dotenv-0.20.0.dist-info/LICENSE | 87 + .../python_dotenv-0.20.0.dist-info/METADATA | 594 + .../python_dotenv-0.20.0.dist-info/RECORD | 23 + .../python_dotenv-0.20.0.dist-info/WHEEL | 5 + .../entry_points.txt | 3 + .../top_level.txt | 1 + .../sniffio-1.2.0.dist-info/INSTALLER | 1 + .../sniffio-1.2.0.dist-info/LICENSE | 3 + .../sniffio-1.2.0.dist-info/LICENSE.APACHE2 | 202 + .../sniffio-1.2.0.dist-info/LICENSE.MIT | 20 + .../sniffio-1.2.0.dist-info/METADATA | 103 + .../sniffio-1.2.0.dist-info/RECORD | 19 + .../sniffio-1.2.0.dist-info/WHEEL | 5 + .../sniffio-1.2.0.dist-info/top_level.txt | 1 + .../Lib/site-packages/sniffio/__init__.py | 14 + .../Lib/site-packages/sniffio/_impl.py | 83 + .../site-packages/sniffio/_tests/__init__.py | 0 .../sniffio/_tests/test_sniffio.py | 67 + .../Lib/site-packages/sniffio/_version.py | 3 + .../Lib/site-packages/sniffio/py.typed | 0 .../starlette-0.19.1.dist-info/INSTALLER | 1 + .../starlette-0.19.1.dist-info/LICENSE.md | 27 + .../starlette-0.19.1.dist-info/METADATA | 179 + .../starlette-0.19.1.dist-info/RECORD | 73 + .../starlette-0.19.1.dist-info/WHEEL | 5 + .../starlette-0.19.1.dist-info/top_level.txt | 1 + .../Lib/site-packages/starlette/__init__.py | 1 + .../Lib/site-packages/starlette/_compat.py | 29 + .../Lib/site-packages/starlette/_pep562.py | 62 + .../site-packages/starlette/applications.py | 283 + .../site-packages/starlette/authentication.py | 151 + .../Lib/site-packages/starlette/background.py | 43 + .../site-packages/starlette/concurrency.py | 65 + .../Lib/site-packages/starlette/config.py | 144 + .../Lib/site-packages/starlette/convertors.py | 87 + .../site-packages/starlette/datastructures.py | 696 ++ .../Lib/site-packages/starlette/endpoints.py | 132 + .../Lib/site-packages/starlette/exceptions.py | 111 + .../site-packages/starlette/formparsers.py | 238 + .../starlette/middleware/__init__.py | 17 + .../starlette/middleware/authentication.py | 52 + .../starlette/middleware/base.py | 75 + .../starlette/middleware/cors.py | 177 + .../starlette/middleware/errors.py | 254 + .../starlette/middleware/gzip.py | 105 + .../starlette/middleware/httpsredirect.py | 19 + .../starlette/middleware/sessions.py | 80 + .../starlette/middleware/trustedhost.py | 60 + .../starlette/middleware/wsgi.py | 140 + .../Lib/site-packages/starlette/py.typed | 0 .../Lib/site-packages/starlette/requests.py | 290 + .../Lib/site-packages/starlette/responses.py | 349 + .../Lib/site-packages/starlette/routing.py | 832 ++ .../Lib/site-packages/starlette/schemas.py | 135 + .../site-packages/starlette/staticfiles.py | 240 + .../Lib/site-packages/starlette/status.py | 206 + .../Lib/site-packages/starlette/templating.py | 105 + .../Lib/site-packages/starlette/testclient.py | 584 + .../Lib/site-packages/starlette/types.py | 9 + .../Lib/site-packages/starlette/websockets.py | 193 + .../INSTALLER | 1 + .../typing_extensions-4.3.0.dist-info/LICENSE | 254 + .../METADATA | 176 + .../typing_extensions-4.3.0.dist-info/RECORD | 7 + .../typing_extensions-4.3.0.dist-info/WHEEL | 4 + .../Lib/site-packages/typing_extensions.py | 2069 +++ .../uvicorn-0.18.3.dist-info/INSTALLER | 1 + .../uvicorn-0.18.3.dist-info/METADATA | 177 + .../uvicorn-0.18.3.dist-info/RECORD | 88 + .../uvicorn-0.18.3.dist-info/REQUESTED | 0 .../uvicorn-0.18.3.dist-info/WHEEL | 4 + .../uvicorn-0.18.3.dist-info/entry_points.txt | 2 + .../licenses/LICENSE.md | 27 + .../Lib/site-packages/uvicorn/__init__.py | 5 + .../Lib/site-packages/uvicorn/__main__.py | 4 + .../Lib/site-packages/uvicorn/_subprocess.py | 76 + .../Lib/site-packages/uvicorn/_types.py | 14 + .../Lib/site-packages/uvicorn/config.py | 591 + .../Lib/site-packages/uvicorn/importer.py | 38 + .../uvicorn/lifespan/__init__.py | 0 .../Lib/site-packages/uvicorn/lifespan/off.py | 12 + .../Lib/site-packages/uvicorn/lifespan/on.py | 137 + .../Lib/site-packages/uvicorn/logging.py | 122 + .../site-packages/uvicorn/loops/__init__.py | 0 .../site-packages/uvicorn/loops/asyncio.py | 10 + .../Lib/site-packages/uvicorn/loops/auto.py | 11 + .../Lib/site-packages/uvicorn/loops/uvloop.py | 7 + .../Lib/site-packages/uvicorn/main.py | 585 + .../uvicorn/middleware/__init__.py | 0 .../site-packages/uvicorn/middleware/asgi2.py | 20 + .../site-packages/uvicorn/middleware/debug.py | 122 + .../uvicorn/middleware/message_logger.py | 89 + .../uvicorn/middleware/proxy_headers.py | 78 + .../site-packages/uvicorn/middleware/wsgi.py | 190 + .../uvicorn/protocols/__init__.py | 0 .../uvicorn/protocols/http/__init__.py | 0 .../uvicorn/protocols/http/auto.py | 14 + .../uvicorn/protocols/http/flow_control.py | 68 + .../uvicorn/protocols/http/h11_impl.py | 557 + .../uvicorn/protocols/http/httptools_impl.py | 579 + .../site-packages/uvicorn/protocols/utils.py | 55 + .../uvicorn/protocols/websockets/__init__.py | 0 .../uvicorn/protocols/websockets/auto.py | 19 + .../protocols/websockets/websockets_impl.py | 350 + .../protocols/websockets/wsproto_impl.py | 322 + .../Lib/site-packages/uvicorn/server.py | 306 + .../uvicorn/supervisors/__init__.py | 21 + .../uvicorn/supervisors/basereload.py | 113 + .../uvicorn/supervisors/multiprocess.py | 74 + .../uvicorn/supervisors/statreload.py | 53 + .../uvicorn/supervisors/watchfilesreload.py | 89 + .../uvicorn/supervisors/watchgodreload.py | 158 + .../Lib/site-packages/uvicorn/workers.py | 90 + .../watchfiles-0.16.1.dist-info/INSTALLER | 1 + .../watchfiles-0.16.1.dist-info/METADATA | 147 + .../watchfiles-0.16.1.dist-info/RECORD | 24 + .../watchfiles-0.16.1.dist-info/WHEEL | 4 + .../entry_points.txt | 2 + .../license_files/LICENSE | 21 + .../Lib/site-packages/watchfiles/__init__.py | 17 + .../Lib/site-packages/watchfiles/__main__.py | 4 + .../site-packages/watchfiles/_rust_notify.pyd | Bin 0 -> 589824 bytes .../site-packages/watchfiles/_rust_notify.pyi | 100 + .../Lib/site-packages/watchfiles/cli.py | 206 + .../Lib/site-packages/watchfiles/filters.py | 147 + .../Lib/site-packages/watchfiles/main.py | 293 + .../Lib/site-packages/watchfiles/py.typed | 1 + .../Lib/site-packages/watchfiles/run.py | 384 + .../Lib/site-packages/watchfiles/version.py | 5 + .../websockets-10.3.dist-info/INSTALLER | 1 + .../websockets-10.3.dist-info/LICENSE | 25 + .../websockets-10.3.dist-info/METADATA | 174 + .../websockets-10.3.dist-info/RECORD | 68 + .../websockets-10.3.dist-info/WHEEL | 5 + .../websockets-10.3.dist-info/top_level.txt | 3 + .../Lib/site-packages/websockets/__init__.py | 114 + .../Lib/site-packages/websockets/__main__.py | 230 + .../Lib/site-packages/websockets/auth.py | 4 + .../Lib/site-packages/websockets/client.py | 347 + .../site-packages/websockets/connection.py | 702 ++ .../websockets/datastructures.py | 200 + .../site-packages/websockets/exceptions.py | 398 + .../websockets/extensions/__init__.py | 4 + .../websockets/extensions/base.py | 128 + .../extensions/permessage_deflate.py | 661 + .../Lib/site-packages/websockets/frames.py | 443 + .../Lib/site-packages/websockets/headers.py | 587 + .../Lib/site-packages/websockets/http.py | 30 + .../Lib/site-packages/websockets/http11.py | 366 + .../Lib/site-packages/websockets/imports.py | 99 + .../websockets/legacy/__init__.py | 0 .../site-packages/websockets/legacy/auth.py | 188 + .../site-packages/websockets/legacy/client.py | 709 ++ .../websockets/legacy/compatibility.py | 13 + .../websockets/legacy/framing.py | 174 + .../websockets/legacy/handshake.py | 165 + .../site-packages/websockets/legacy/http.py | 201 + .../websockets/legacy/protocol.py | 1605 +++ .../site-packages/websockets/legacy/server.py | 1156 ++ .../Lib/site-packages/websockets/py.typed | 0 .../Lib/site-packages/websockets/server.py | 521 + .../websockets/speedups.cp37-win_amd64.pyd | Bin 0 -> 11264 bytes .../Lib/site-packages/websockets/streams.py | 151 + .../Lib/site-packages/websockets/typing.py | 60 + .../Lib/site-packages/websockets/uri.py | 108 + .../Lib/site-packages/websockets/utils.py | 51 + .../Lib/site-packages/websockets/version.py | 78 + .../python-3.7.2.amd64/Scripts/dotenv.exe | Bin 0 -> 106369 bytes .../python-3.7.2.amd64/Scripts/uvicorn.exe | Bin 0 -> 106373 bytes .../python-3.7.2.amd64/Scripts/watchfiles.exe | Bin 0 -> 106373 bytes Sources/pyOpenRPA/Orchestrator/Server.py | 499 +- .../Orchestrator/__Orchestrator__.py | 9 +- Studio/pyOpenRPA.Studio_x64.cmd | 3 +- 405 files changed, 89952 insertions(+), 287 deletions(-) create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/entry_points.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_asyncio.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_trio.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_compat.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_eventloop.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_exceptions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_fileio.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_resources.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_signals.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_sockets.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_streams.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_subprocesses.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_synchronization.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_tasks.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_testing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_typedattr.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_resources.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_sockets.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_streams.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_subprocesses.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_tasks.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_testing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/from_thread.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/lowlevel.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/pytest_plugin.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/buffered.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/file.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/memory.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/stapled.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/text.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/tls.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_process.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_thread.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/LICENSE.rst create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_compat.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_termui_impl.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_textwrap.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_winconsole.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/core.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/decorators.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/exceptions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/formatting.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/globals.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/parser.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/shell_completion.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/termui.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/testing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/types.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/cli.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/ipython.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/main.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/parser.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/variables.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/version.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/REQUESTED create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/applications.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/background.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/concurrency.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/datastructures.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/models.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/encoders.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exception_handlers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exceptions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/logger.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/asyncexitstack.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/cors.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/gzip.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/httpsredirect.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/trustedhost.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/wsgi.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/constants.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/docs.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/models.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/param_functions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/params.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/requests.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/responses.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/routing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/api_key.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/base.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/http.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/oauth2.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/open_id_connect_url.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/staticfiles.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/templating.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/testclient.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/types.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/websockets.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/LICENSE.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_abnf.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_connection.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_events.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_headers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_readers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_receivebuffer.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_state.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_util.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_version.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_writers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/data/test-file create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/helpers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_against_stdlib_http.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_connection.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_events.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_headers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_helpers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_io.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_receivebuffer.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_state.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_util.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/_version.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/errors.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/parser.c create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/parser.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/url_parser.c create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/url_parser.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/entry_points.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/__init__.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/_hypothesis_plugin.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/_hypothesis_plugin.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/annotated_types.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/annotated_types.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/class_validators.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/class_validators.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/color.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/color.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/config.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/config.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/dataclasses.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/dataclasses.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/datetime_parse.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/datetime_parse.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/decorator.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/decorator.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/env_settings.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/env_settings.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/error_wrappers.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/error_wrappers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/errors.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/errors.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/fields.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/fields.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/generics.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/json.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/json.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/main.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/main.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/mypy.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/mypy.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/networks.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/networks.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/parse.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/parse.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/schema.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/schema.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/tools.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/tools.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/types.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/types.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/typing.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/typing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/utils.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/validators.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/validators.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/version.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/version.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/entry_points.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.APACHE2 create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.MIT create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_impl.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_tests/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_tests/test_sniffio.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_version.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/LICENSE.md create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_compat.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_pep562.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/applications.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/authentication.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/background.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/concurrency.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/config.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/convertors.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/datastructures.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/endpoints.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/exceptions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/formparsers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/authentication.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/base.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/cors.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/errors.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/gzip.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/httpsredirect.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/sessions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/trustedhost.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/wsgi.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/requests.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/responses.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/routing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/schemas.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/staticfiles.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/status.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/templating.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/testclient.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/types.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/websockets.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/REQUESTED create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/entry_points.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/licenses/LICENSE.md create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__main__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_subprocess.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_types.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/config.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/importer.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/off.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/on.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/logging.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/asyncio.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/auto.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/uvloop.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/main.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/asgi2.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/debug.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/message_logger.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/proxy_headers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/wsgi.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/auto.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/flow_control.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/h11_impl.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/httptools_impl.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/auto.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/websockets_impl.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/wsproto_impl.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/server.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/basereload.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/multiprocess.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/statreload.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchfilesreload.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchgodreload.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/workers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/entry_points.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/license_files/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__main__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/_rust_notify.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/_rust_notify.pyi create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/cli.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/filters.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/main.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/run.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/version.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/INSTALLER create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/LICENSE create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/METADATA create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/RECORD create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/WHEEL create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/top_level.txt create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__main__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/auth.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/client.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/connection.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/datastructures.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/exceptions.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/base.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/permessage_deflate.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/frames.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/headers.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http11.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/imports.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/__init__.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/auth.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/client.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/compatibility.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/framing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/handshake.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/http.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/protocol.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/server.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/py.typed create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/server.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/speedups.cp37-win_amd64.pyd create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/streams.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/typing.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/uri.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/utils.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/version.py create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Scripts/dotenv.exe create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Scripts/uvicorn.exe create mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Scripts/watchfiles.exe diff --git a/Agent/start-daemon.cmd b/Agent/start-daemon.cmd index d308709d..6ddca62e 100755 --- a/Agent/start-daemon.cmd +++ b/Agent/start-daemon.cmd @@ -1,4 +1,5 @@ -cd %~dp0 +chcp 65001 +cd /d "%~dp0" taskkill /im "orpa-agent.exe" /F /fi "username eq %username%" copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\pythonw.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\orpa-agent.exe .\..\Resources\WPy64-3720\python-3.7.2.amd64\orpa-agent.exe "config.py" diff --git a/Agent/start.cmd b/Agent/start.cmd index f3afdf35..16d3de8e 100755 --- a/Agent/start.cmd +++ b/Agent/start.cmd @@ -1,4 +1,5 @@ -cd %~dp0 +chcp 65001 +cd /d "%~dp0" taskkill /im "orpa-agent.exe" /F /fi "username eq %username%" copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\orpa-agent.exe .\..\Resources\WPy64-3720\python-3.7.2.amd64\orpa-agent.exe "config.py" diff --git a/Orchestrator/start.cmd b/Orchestrator/start.cmd index 2fba96d6..2ce50d70 100755 --- a/Orchestrator/start.cmd +++ b/Orchestrator/start.cmd @@ -1,4 +1,5 @@ -cd %~dp0 +chcp 65001 +cd /d "%~dp0" taskkill /im "orpa-orc.exe" /F /fi "username eq %username%" copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\orpa-orc.exe .\..\Resources\WPy64-3720\python-3.7.2.amd64\orpa-orc.exe "config.py" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/LICENSE new file mode 100644 index 00000000..104eebf5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/METADATA new file mode 100644 index 00000000..600c1fe0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/METADATA @@ -0,0 +1,102 @@ +Metadata-Version: 2.1 +Name: anyio +Version: 3.6.1 +Summary: High level compatibility layer for multiple asynchronous event loop implementations +Author: Alex Grönholm +Author-email: alex.gronholm@nextday.fi +License: MIT +Project-URL: Documentation, https://anyio.readthedocs.io/en/latest/ +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: License :: OSI Approved :: MIT License +Classifier: Framework :: AnyIO +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Requires-Python: >=3.6.2 +License-File: LICENSE +Requires-Dist: idna (>=2.8) +Requires-Dist: sniffio (>=1.1) +Requires-Dist: contextvars ; python_version < "3.7" +Requires-Dist: dataclasses ; python_version < "3.7" +Requires-Dist: typing-extensions ; python_version < "3.8" +Provides-Extra: doc +Requires-Dist: packaging ; extra == 'doc' +Requires-Dist: sphinx-rtd-theme ; extra == 'doc' +Requires-Dist: sphinx-autodoc-typehints (>=1.2.0) ; extra == 'doc' +Provides-Extra: test +Requires-Dist: coverage[toml] (>=4.5) ; extra == 'test' +Requires-Dist: hypothesis (>=4.0) ; extra == 'test' +Requires-Dist: pytest (>=7.0) ; extra == 'test' +Requires-Dist: pytest-mock (>=3.6.1) ; extra == 'test' +Requires-Dist: trustme ; extra == 'test' +Requires-Dist: contextlib2 ; (python_version < "3.7") and extra == 'test' +Requires-Dist: uvloop (<0.15) ; (python_version < "3.7" and (platform_python_implementation == "CPython" and platform_system != "Windows")) and extra == 'test' +Requires-Dist: mock (>=4) ; (python_version < "3.8") and extra == 'test' +Requires-Dist: uvloop (>=0.15) ; (python_version >= "3.7" and (platform_python_implementation == "CPython" and platform_system != "Windows")) and extra == 'test' +Provides-Extra: trio +Requires-Dist: trio (>=0.16) ; extra == 'trio' + +.. 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 native libraries of your chosen backend. + +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 +* Asynchronous file I/O (using worker threads) +* Signal handling + +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/ +.. _Hypothesis: https://hypothesis.works/ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/RECORD new file mode 100644 index 00000000..77625c27 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/RECORD @@ -0,0 +1,82 @@ +anyio-3.6.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +anyio-3.6.1.dist-info/LICENSE,sha256=U2GsncWPLvX9LpsJxoKXwX8ElQkJu8gCO9uC6s8iwrA,1081 +anyio-3.6.1.dist-info/METADATA,sha256=cXu3CLppFqT_rBl4Eo2HOb0J1zm6Ltu_tMFuzjuQnew,4654 +anyio-3.6.1.dist-info/RECORD,, +anyio-3.6.1.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +anyio-3.6.1.dist-info/entry_points.txt,sha256=_d6Yu6uiaZmNe0CydowirE9Cmg7zUL2g08tQpoS3Qvc,39 +anyio-3.6.1.dist-info/top_level.txt,sha256=QglSMiWX8_5dpoVAEIHdEYzvqFMdSYWmCj6tYw2ITkQ,6 +anyio/__init__.py,sha256=M2R8dk6L5gL5lXHArzpSfEn2oH5jMyUKhzyrkRiv2AM,4037 +anyio/__pycache__/__init__.cpython-37.pyc,, +anyio/__pycache__/from_thread.cpython-37.pyc,, +anyio/__pycache__/lowlevel.cpython-37.pyc,, +anyio/__pycache__/pytest_plugin.cpython-37.pyc,, +anyio/__pycache__/to_process.cpython-37.pyc,, +anyio/__pycache__/to_thread.cpython-37.pyc,, +anyio/_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/_backends/__pycache__/__init__.cpython-37.pyc,, +anyio/_backends/__pycache__/_asyncio.cpython-37.pyc,, +anyio/_backends/__pycache__/_trio.cpython-37.pyc,, +anyio/_backends/_asyncio.py,sha256=ZJDvRwfS4wv9WWcqWledNJyl8hx8A8-m9-gSKAJ6nBM,69238 +anyio/_backends/_trio.py,sha256=CebCaqr8Szi6uCnUzwtBRLfUitR5OnDT_wfH-KiqvBQ,29696 +anyio/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/_core/__pycache__/__init__.cpython-37.pyc,, +anyio/_core/__pycache__/_compat.cpython-37.pyc,, +anyio/_core/__pycache__/_eventloop.cpython-37.pyc,, +anyio/_core/__pycache__/_exceptions.cpython-37.pyc,, +anyio/_core/__pycache__/_fileio.cpython-37.pyc,, +anyio/_core/__pycache__/_resources.cpython-37.pyc,, +anyio/_core/__pycache__/_signals.cpython-37.pyc,, +anyio/_core/__pycache__/_sockets.cpython-37.pyc,, +anyio/_core/__pycache__/_streams.cpython-37.pyc,, +anyio/_core/__pycache__/_subprocesses.cpython-37.pyc,, +anyio/_core/__pycache__/_synchronization.cpython-37.pyc,, +anyio/_core/__pycache__/_tasks.cpython-37.pyc,, +anyio/_core/__pycache__/_testing.cpython-37.pyc,, +anyio/_core/__pycache__/_typedattr.cpython-37.pyc,, +anyio/_core/_compat.py,sha256=X99W70r-O-JLdkKNtbddcIY5H2Nyg3Nk34oUYE9WZRs,5790 +anyio/_core/_eventloop.py,sha256=DRn_hy679LtsJFsPX7dXjDv72bLtSFkTnWY9WVVfgCQ,4108 +anyio/_core/_exceptions.py,sha256=1wqraNldZroYkoyB0HZStAruz_7yDCBaW-4zYwsKj8s,2904 +anyio/_core/_fileio.py,sha256=au82uZXZX4fia8EoZq_E-JDwZFKe6ZtI0J6IkxK8FmQ,18298 +anyio/_core/_resources.py,sha256=M_uN-90N8eSsWuvo-0xluWU_OG2BTyccAgsQ7XtHxzs,399 +anyio/_core/_signals.py,sha256=D4btJN527tAADspKBeNKaCds-ZcEZJP8LWM_MjVuQRA,827 +anyio/_core/_sockets.py,sha256=fW_Cbg6kfw4xgYuVuWbcWrAYspOcDSEjwxVATMzf2fo,19820 +anyio/_core/_streams.py,sha256=gjT5xChJ1OoV8nNinljSv1yW4nqUS-QzZzIydQz3exQ,1494 +anyio/_core/_subprocesses.py,sha256=pcchMI2OII0QSjiVxRiTEz4M0B7TlQPzGurfCuka-xc,5049 +anyio/_core/_synchronization.py,sha256=xOOG4hF9783N6E2IcD3YKiukguA5bPrj6BodDsKNaJY,16822 +anyio/_core/_tasks.py,sha256=ebGLjHvwL6I9aGyPwvCig1drebSVYFzvY3pnN3TsB4o,5273 +anyio/_core/_testing.py,sha256=VZka_yebIhJ6mJ6Vo_ilO3Nbz53ieqg0WBijwciMwdY,2196 +anyio/_core/_typedattr.py,sha256=k5-wBvMlDlKHIpn18INVnXAlGwI3CrAvPmWoceHjnOQ,2534 +anyio/abc/__init__.py,sha256=hMa47CMs5O1twC2bBcSbzwX-3Q08BAgAPTRekQobb3E,2123 +anyio/abc/__pycache__/__init__.cpython-37.pyc,, +anyio/abc/__pycache__/_resources.cpython-37.pyc,, +anyio/abc/__pycache__/_sockets.cpython-37.pyc,, +anyio/abc/__pycache__/_streams.cpython-37.pyc,, +anyio/abc/__pycache__/_subprocesses.cpython-37.pyc,, +anyio/abc/__pycache__/_tasks.cpython-37.pyc,, +anyio/abc/__pycache__/_testing.cpython-37.pyc,, +anyio/abc/_resources.py,sha256=js737mWPG6IW0fH8W4Tz9eNWLztse7dKxEC61z934Vk,752 +anyio/abc/_sockets.py,sha256=i1VdcJTLAuRlYeZoL6s5RBSWbX62Cu6ln5YZBL2YrWk,5754 +anyio/abc/_streams.py,sha256=0g70fhKAzbnK0KKmWwRgwmKdApBwduAcVj4TpjSzjzU,6501 +anyio/abc/_subprocesses.py,sha256=iREP_YQ91it88lDU4XIcI3HZ9HUvV5UmjQk_sSPonrw,2071 +anyio/abc/_tasks.py,sha256=mQQd1DANqpySKyehVVPdMfi_UEG49zZUJpt5blunOjg,3119 +anyio/abc/_testing.py,sha256=ifKCUPzcQdHAEGO-weu2GQvzjMQPPIWO24mQ0z6zkdU,1928 +anyio/from_thread.py,sha256=nSq6mafYMqwxKmzdJyISg8cp-AyBj9rxZPMt_b7klSM,16497 +anyio/lowlevel.py,sha256=W4ydshns7f86YuSESFc2igTf46AWMXnGPQGsY_Esl2E,4679 +anyio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/pytest_plugin.py,sha256=kWj2B8BJehePJd1sztRBmJBRh8O4hk1oGSYQRlX5Gr8,5134 +anyio/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/streams/__pycache__/__init__.cpython-37.pyc,, +anyio/streams/__pycache__/buffered.cpython-37.pyc,, +anyio/streams/__pycache__/file.cpython-37.pyc,, +anyio/streams/__pycache__/memory.cpython-37.pyc,, +anyio/streams/__pycache__/stapled.cpython-37.pyc,, +anyio/streams/__pycache__/text.cpython-37.pyc,, +anyio/streams/__pycache__/tls.cpython-37.pyc,, +anyio/streams/buffered.py,sha256=FegOSO4Xcxa5SaDfU1A3ZkTTxaPrv6G435Y_giZ8k44,4437 +anyio/streams/file.py,sha256=pujJ-m6BX-gOLnVoZwkE5kh-YDs5Vx9eJFVkvliQ0S4,4353 +anyio/streams/memory.py,sha256=3RGeZoevoGIgBWfD2_X1cqxIPOz-BqQkRf6lUcOnBYc,9209 +anyio/streams/stapled.py,sha256=0E0V15v8M5GVelpHe5RT0S33tQ9hGe4ZCXo_KJEjtt4,4258 +anyio/streams/text.py,sha256=WRFyjsRpBjQKdCmR4ZuzYTEAJqGx2s5oTJmGI1C6Ng0,5014 +anyio/streams/tls.py,sha256=-WXGsMV14XHXAxc38WpBvGusjuY7e449g4UCEHIlnWw,12040 +anyio/to_process.py,sha256=hu0ES3HJC-VEjcdPJMzAzjyTaekaCNToO3coj3jvnus,9247 +anyio/to_thread.py,sha256=VeMQoo8Va2zz0WFk2p123QikDpqk2wYZGw20COC3wqw,2124 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/entry_points.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/entry_points.txt new file mode 100644 index 00000000..44dd9bdc --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[pytest11] +anyio = anyio.pytest_plugin diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/top_level.txt new file mode 100644 index 00000000..c77c069e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio-3.6.1.dist-info/top_level.txt @@ -0,0 +1 @@ +anyio diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/__init__.py new file mode 100644 index 00000000..6e81178c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/__init__.py @@ -0,0 +1,167 @@ +__all__ = ( + "maybe_async", + "maybe_async_cm", + "run", + "sleep", + "sleep_forever", + "sleep_until", + "current_time", + "get_all_backends", + "get_cancelled_exc_class", + "BrokenResourceError", + "BrokenWorkerProcess", + "BusyResourceError", + "ClosedResourceError", + "DelimiterNotFound", + "EndOfStream", + "ExceptionGroup", + "IncompleteRead", + "TypedAttributeLookupError", + "WouldBlock", + "AsyncFile", + "Path", + "open_file", + "wrap_file", + "aclose_forcefully", + "open_signal_receiver", + "connect_tcp", + "connect_unix", + "create_tcp_listener", + "create_unix_listener", + "create_udp_socket", + "create_connected_udp_socket", + "getaddrinfo", + "getnameinfo", + "wait_socket_readable", + "wait_socket_writable", + "create_memory_object_stream", + "run_process", + "open_process", + "create_lock", + "CapacityLimiter", + "CapacityLimiterStatistics", + "Condition", + "ConditionStatistics", + "Event", + "EventStatistics", + "Lock", + "LockStatistics", + "Semaphore", + "SemaphoreStatistics", + "create_condition", + "create_event", + "create_semaphore", + "create_capacity_limiter", + "open_cancel_scope", + "fail_after", + "move_on_after", + "current_effective_deadline", + "TASK_STATUS_IGNORED", + "CancelScope", + "create_task_group", + "TaskInfo", + "get_current_task", + "get_running_tasks", + "wait_all_tasks_blocked", + "run_sync_in_worker_thread", + "run_async_from_thread", + "run_sync_from_thread", + "current_default_worker_thread_limiter", + "create_blocking_portal", + "start_blocking_portal", + "typed_attribute", + "TypedAttributeSet", + "TypedAttributeProvider", +) + +from typing import Any + +from ._core._compat import maybe_async, maybe_async_cm +from ._core._eventloop import ( + current_time, + get_all_backends, + get_cancelled_exc_class, + run, + sleep, + sleep_forever, + sleep_until, +) +from ._core._exceptions import ( + BrokenResourceError, + BrokenWorkerProcess, + BusyResourceError, + ClosedResourceError, + DelimiterNotFound, + EndOfStream, + ExceptionGroup, + IncompleteRead, + TypedAttributeLookupError, + WouldBlock, +) +from ._core._fileio import AsyncFile, Path, open_file, wrap_file +from ._core._resources import aclose_forcefully +from ._core._signals import open_signal_receiver +from ._core._sockets import ( + connect_tcp, + connect_unix, + create_connected_udp_socket, + create_tcp_listener, + create_udp_socket, + create_unix_listener, + getaddrinfo, + getnameinfo, + wait_socket_readable, + wait_socket_writable, +) +from ._core._streams import create_memory_object_stream +from ._core._subprocesses import open_process, run_process +from ._core._synchronization import ( + CapacityLimiter, + CapacityLimiterStatistics, + Condition, + ConditionStatistics, + Event, + EventStatistics, + Lock, + LockStatistics, + Semaphore, + SemaphoreStatistics, + create_capacity_limiter, + create_condition, + create_event, + create_lock, + create_semaphore, +) +from ._core._tasks import ( + TASK_STATUS_IGNORED, + CancelScope, + create_task_group, + current_effective_deadline, + fail_after, + move_on_after, + open_cancel_scope, +) +from ._core._testing import ( + TaskInfo, + get_current_task, + get_running_tasks, + wait_all_tasks_blocked, +) +from ._core._typedattr import TypedAttributeProvider, TypedAttributeSet, typed_attribute + +# Re-exported here, for backwards compatibility +# isort: off +from .to_thread import current_default_worker_thread_limiter, run_sync_in_worker_thread +from .from_thread import ( + create_blocking_portal, + run_async_from_thread, + run_sync_from_thread, + start_blocking_portal, +) + +# Re-export imports so they look like they live directly in this package +key: str +value: Any +for key, value in list(locals().items()): + if getattr(value, "__module__", "").startswith("anyio."): + value.__module__ = __name__ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_asyncio.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_asyncio.py new file mode 100644 index 00000000..d2bbc94c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_asyncio.py @@ -0,0 +1,2181 @@ +import array +import asyncio +import concurrent.futures +import math +import socket +import sys +from asyncio.base_events import _run_until_complete_cb # type: ignore[attr-defined] +from collections import OrderedDict, deque +from concurrent.futures import Future +from contextvars import Context, copy_context +from dataclasses import dataclass +from functools import partial, wraps +from inspect import ( + CORO_RUNNING, + CORO_SUSPENDED, + GEN_RUNNING, + GEN_SUSPENDED, + getcoroutinestate, + getgeneratorstate, +) +from io import IOBase +from os import PathLike +from queue import Queue +from socket import AddressFamily, SocketKind +from threading import Thread +from types import TracebackType +from typing import ( + IO, + Any, + AsyncGenerator, + Awaitable, + Callable, + Collection, + Coroutine, + Deque, + Dict, + Generator, + Iterable, + List, + Mapping, + Optional, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, +) +from weakref import WeakKeyDictionary + +import sniffio + +from .. import CapacityLimiterStatistics, EventStatistics, TaskInfo, abc +from .._core._compat import DeprecatedAsyncContextManager, DeprecatedAwaitable +from .._core._eventloop import claim_worker_thread, threadlocals +from .._core._exceptions import ( + BrokenResourceError, + BusyResourceError, + ClosedResourceError, + EndOfStream, +) +from .._core._exceptions import ExceptionGroup as BaseExceptionGroup +from .._core._exceptions import WouldBlock +from .._core._sockets import GetAddrInfoReturnType, convert_ipv6_sockaddr +from .._core._synchronization import CapacityLimiter as BaseCapacityLimiter +from .._core._synchronization import Event as BaseEvent +from .._core._synchronization import ResourceGuard +from .._core._tasks import CancelScope as BaseCancelScope +from ..abc import IPSockAddrType, UDPPacketType +from ..lowlevel import RunVar + +if sys.version_info >= (3, 8): + + def get_coro(task: asyncio.Task) -> Union[Generator, Awaitable[Any]]: + return task.get_coro() + +else: + + def get_coro(task: asyncio.Task) -> Union[Generator, Awaitable[Any]]: + return task._coro + + +if sys.version_info >= (3, 7): + from asyncio import all_tasks, create_task, current_task, get_running_loop + from asyncio import run as native_run + + def _get_task_callbacks(task: asyncio.Task) -> Iterable[Callable]: + return [cb for cb, context in task._callbacks] # type: ignore[attr-defined] + +else: + _T = TypeVar("_T") + + def _get_task_callbacks(task: asyncio.Task) -> Iterable[Callable]: + return task._callbacks + + def native_run(main, *, debug=False): + # Snatched from Python 3.7 + from asyncio import coroutines, events, tasks + + def _cancel_all_tasks(loop): + to_cancel = all_tasks(loop) + if not to_cancel: + return + + for task in to_cancel: + task.cancel() + + loop.run_until_complete( + tasks.gather(*to_cancel, loop=loop, 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, + } + ) + + if events._get_running_loop() is not None: + raise RuntimeError( + "asyncio.run() cannot be called from a running event loop" + ) + + if not coroutines.iscoroutine(main): + raise ValueError(f"a coroutine was expected, got {main!r}") + + loop = events.new_event_loop() + try: + events.set_event_loop(loop) + loop.set_debug(debug) + return loop.run_until_complete(main) + finally: + try: + _cancel_all_tasks(loop) + loop.run_until_complete(loop.shutdown_asyncgens()) + finally: + events.set_event_loop(None) + loop.close() + + def create_task( + coro: Union[Generator[Any, None, _T], Awaitable[_T]], *, name: object = None + ) -> asyncio.Task: + return get_running_loop().create_task(coro) + + def get_running_loop() -> asyncio.AbstractEventLoop: + loop = asyncio._get_running_loop() + if loop is not None: + return loop + else: + raise RuntimeError("no running event loop") + + def all_tasks( + loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> Set[asyncio.Task]: + """Return a set of all tasks for the loop.""" + from asyncio import Task + + if loop is None: + loop = get_running_loop() + + return {t for t in Task.all_tasks(loop) if not t.done()} + + def current_task( + loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> Optional[asyncio.Task]: + if loop is None: + loop = get_running_loop() + + return asyncio.Task.current_task(loop) + + +T_Retval = TypeVar("T_Retval") + +# Check whether there is native support for task names in asyncio (3.8+) +_native_task_names = hasattr(asyncio.Task, "get_name") + + +_root_task: RunVar[Optional[asyncio.Task]] = 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(): + for cb in _get_task_callbacks(task): + 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() +) # type: WeakKeyDictionary[asyncio.AbstractEventLoop, Any] + +current_token = get_running_loop + + +def _task_started(task: asyncio.Task) -> bool: + """Return ``True`` if the task has been started and has not finished.""" + coro = cast(Coroutine[Any, Any, Any], get_coro(task)) + try: + return getcoroutinestate(coro) in (CORO_RUNNING, CORO_SUSPENDED) + except AttributeError: + try: + return getgeneratorstate(cast(Generator, coro)) in ( + GEN_RUNNING, + GEN_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") + + +def _maybe_set_event_loop_policy( + policy: Optional[asyncio.AbstractEventLoopPolicy], use_uvloop: bool +) -> None: + # On CPython, use uvloop when possible if no other policy has been given and if not + # explicitly disabled + if policy is None and use_uvloop and sys.implementation.name == "cpython": + try: + import uvloop + except ImportError: + pass + else: + # Test for missing shutdown_default_executor() (uvloop 0.14.0 and earlier) + if not hasattr( + asyncio.AbstractEventLoop, "shutdown_default_executor" + ) or hasattr(uvloop.loop.Loop, "shutdown_default_executor"): + policy = uvloop.EventLoopPolicy() + + if policy is not None: + asyncio.set_event_loop_policy(policy) + + +def run( + func: Callable[..., Awaitable[T_Retval]], + *args: object, + debug: bool = False, + use_uvloop: bool = False, + policy: Optional[asyncio.AbstractEventLoopPolicy] = None, +) -> T_Retval: + @wraps(func) + async def wrapper() -> T_Retval: + task = cast(asyncio.Task, current_task()) + task_state = TaskState(None, get_callable_name(func), None) + _task_states[task] = task_state + if _native_task_names: + task.set_name(task_state.name) + + try: + return await func(*args) + finally: + del _task_states[task] + + _maybe_set_event_loop_policy(policy, use_uvloop) + return native_run(wrapper(), debug=debug) + + +# +# Miscellaneous +# + +sleep = asyncio.sleep + + +# +# Timeouts and cancellation +# + +CancelledError = asyncio.CancelledError + + +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: Optional[CancelScope] = None + self._cancel_called = False + self._active = False + self._timeout_handle: Optional[asyncio.TimerHandle] = None + self._cancel_handle: Optional[asyncio.Handle] = None + self._tasks: Set[asyncio.Task] = set() + self._host_task: Optional[asyncio.Task] = None + self._timeout_expired = False + + 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_name = host_task.get_name() if _native_task_names else None + task_state = TaskState(None, task_name, self) + _task_states[host_task] = task_state + else: + self._parent_scope = task_state.cancel_scope + task_state.cancel_scope = self + + self._timeout() + self._active = True + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + 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" + ) + + self._active = False + if self._timeout_handle: + self._timeout_handle.cancel() + self._timeout_handle = None + + self._tasks.remove(self._host_task) + + host_task_state.cancel_scope = self._parent_scope + + # Restart the cancellation effort in the farthest directly cancelled parent scope if this + # one was shielded + if self._shield: + self._deliver_cancellation_to_parent() + + if exc_val is not None: + exceptions = ( + exc_val.exceptions if isinstance(exc_val, ExceptionGroup) else [exc_val] + ) + if all(isinstance(exc, CancelledError) for exc in exceptions): + if self._timeout_expired: + return True + elif not self._cancel_called: + # Task was cancelled natively + return None + elif not self._parent_cancelled(): + # This scope was directly cancelled + return True + + return None + + def _timeout(self) -> None: + if self._deadline != math.inf: + loop = get_running_loop() + if loop.time() >= self._deadline: + self._timeout_expired = True + self.cancel() + else: + self._timeout_handle = loop.call_at(self._deadline, self._timeout) + + def _deliver_cancellation(self) -> None: + """ + Deliver cancellation to directly contained tasks and nested cancel scopes. + + Schedule another run at the end if we still have tasks eligible for cancellation. + """ + should_retry = False + current = current_task() + for task in self._tasks: + if task._must_cancel: # type: ignore[attr-defined] + continue + + # The task is eligible for cancellation if it has started and is not in a cancel + # scope shielded from this one + cancel_scope = _task_states[task].cancel_scope + while cancel_scope is not self: + if cancel_scope is None or cancel_scope._shield: + break + else: + cancel_scope = cancel_scope._parent_scope + else: + should_retry = True + if task is not current and ( + task is self._host_task or _task_started(task) + ): + task.cancel() + + # Schedule another callback if there are still tasks left + if should_retry: + self._cancel_handle = get_running_loop().call_soon( + self._deliver_cancellation + ) + else: + self._cancel_handle = None + + def _deliver_cancellation_to_parent(self) -> None: + """Start cancellation effort in the farthest directly cancelled parent scope""" + scope = self._parent_scope + scope_to_cancel: Optional[CancelScope] = None + while scope is not None: + if scope._cancel_called and scope._cancel_handle is None: + scope_to_cancel = scope + + # No point in looking beyond any shielded scope + if scope._shield: + break + + scope = scope._parent_scope + + if scope_to_cancel is not None: + scope_to_cancel._deliver_cancellation() + + def _parent_cancelled(self) -> bool: + # Check whether any parent has been cancelled + cancel_scope = self._parent_scope + while cancel_scope is not None and not cancel_scope._shield: + if cancel_scope._cancel_called: + return True + else: + cancel_scope = cancel_scope._parent_scope + + return False + + def cancel(self) -> DeprecatedAwaitable: + if not self._cancel_called: + if self._timeout_handle: + self._timeout_handle.cancel() + self._timeout_handle = None + + self._cancel_called = True + self._deliver_cancellation() + + return DeprecatedAwaitable(self.cancel) + + @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 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._deliver_cancellation_to_parent() + + +async def checkpoint() -> None: + await sleep(0) + + +async def checkpoint_if_cancelled() -> 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 + + +async def cancel_shielded_checkpoint() -> None: + with CancelScope(shield=True): + await sleep(0) + + +def current_effective_deadline() -> float: + try: + cancel_scope = _task_states[current_task()].cancel_scope # type: ignore[index] + except KeyError: + return math.inf + + deadline = math.inf + while cancel_scope: + deadline = min(deadline, cancel_scope.deadline) + if cancel_scope.shield: + break + else: + cancel_scope = cancel_scope._parent_scope + + return deadline + + +def current_time() -> float: + return get_running_loop().time() + + +# +# 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", "name", "cancel_scope" + + def __init__( + self, + parent_id: Optional[int], + name: Optional[str], + cancel_scope: Optional[CancelScope], + ): + self.parent_id = parent_id + self.name = name + self.cancel_scope = cancel_scope + + +_task_states = WeakKeyDictionary() # type: WeakKeyDictionary[asyncio.Task, TaskState] + + +# +# Task groups +# + + +class ExceptionGroup(BaseExceptionGroup): + def __init__(self, exceptions: List[BaseException]): + super().__init__() + self.exceptions = exceptions + + +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: object = None) -> None: + try: + self._future.set_result(value) + except asyncio.InvalidStateError: + 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 + + +class TaskGroup(abc.TaskGroup): + def __init__(self) -> None: + self.cancel_scope: CancelScope = CancelScope() + self._active = False + self._exceptions: List[BaseException] = [] + + async def __aenter__(self) -> "TaskGroup": + self.cancel_scope.__enter__() + self._active = True + return self + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + ignore_exception = self.cancel_scope.__exit__(exc_type, exc_val, exc_tb) + if exc_val is not None: + self.cancel_scope.cancel() + self._exceptions.append(exc_val) + + while self.cancel_scope._tasks: + try: + await asyncio.wait(self.cancel_scope._tasks) + except asyncio.CancelledError: + self.cancel_scope.cancel() + + self._active = False + if not self.cancel_scope._parent_cancelled(): + exceptions = self._filter_cancellation_errors(self._exceptions) + else: + exceptions = self._exceptions + + try: + if len(exceptions) > 1: + if all( + isinstance(e, CancelledError) and not e.args for e in exceptions + ): + # Tasks were cancelled natively, without a cancellation message + raise CancelledError + else: + raise ExceptionGroup(exceptions) + elif exceptions and exceptions[0] is not exc_val: + raise exceptions[0] + except BaseException as exc: + # Clear the context here, as it can only be done in-flight. + # If the context is not cleared, it can result in recursive tracebacks (see #145). + exc.__context__ = None + raise + + return ignore_exception + + @staticmethod + def _filter_cancellation_errors( + exceptions: Sequence[BaseException], + ) -> List[BaseException]: + filtered_exceptions: List[BaseException] = [] + for exc in exceptions: + if isinstance(exc, ExceptionGroup): + new_exceptions = TaskGroup._filter_cancellation_errors(exc.exceptions) + if len(new_exceptions) > 1: + filtered_exceptions.append(exc) + elif len(new_exceptions) == 1: + filtered_exceptions.append(new_exceptions[0]) + elif new_exceptions: + new_exc = ExceptionGroup(new_exceptions) + new_exc.__cause__ = exc.__cause__ + new_exc.__context__ = exc.__context__ + new_exc.__traceback__ = exc.__traceback__ + filtered_exceptions.append(new_exc) + elif not isinstance(exc, CancelledError) or exc.args: + filtered_exceptions.append(exc) + + return filtered_exceptions + + async def _run_wrapped_task( + self, coro: Coroutine, task_status_future: Optional[asyncio.Future] + ) -> None: + # This is the code path for Python 3.6 and 3.7 on which asyncio freaks out if a task raises + # a BaseException. + __traceback_hide__ = __tracebackhide__ = True # noqa: F841 + task = cast(asyncio.Task, current_task()) + try: + await coro + except BaseException as exc: + if task_status_future is None or task_status_future.done(): + self._exceptions.append(exc) + self.cancel_scope.cancel() + else: + task_status_future.set_exception(exc) + else: + if 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()") + ) + finally: + if task in self.cancel_scope._tasks: + self.cancel_scope._tasks.remove(task) + del _task_states[task] + + def _spawn( + self, + func: Callable[..., Coroutine], + args: tuple, + name: object, + task_status_future: Optional[asyncio.Future] = None, + ) -> asyncio.Task: + def task_done(_task: asyncio.Task) -> None: + # This is the code path for Python 3.8+ + assert _task in self.cancel_scope._tasks + self.cancel_scope._tasks.remove(_task) + del _task_states[_task] + + try: + exc = _task.exception() + except CancelledError as e: + while isinstance(e.__context__, CancelledError): + e = e.__context__ + + exc = e + + if exc is not None: + if task_status_future is None or task_status_future.done(): + self._exceptions.append(exc) + 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." + ) + + options = {} + name = get_callable_name(func) if name is None else str(name) + if _native_task_names: + options["name"] = name + + 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 asyncio.iscoroutine(coro): + raise TypeError( + f"Expected an async function, but {func} appears to be synchronous" + ) + + foreign_coro = not hasattr(coro, "cr_frame") and not hasattr(coro, "gi_frame") + if foreign_coro or sys.version_info < (3, 8): + coro = self._run_wrapped_task(coro, task_status_future) + + task = create_task(coro, **options) + if not foreign_coro and sys.version_info >= (3, 8): + task.add_done_callback(task_done) + + # Make the spawned task inherit the task group's cancel scope + _task_states[task] = TaskState( + parent_id=parent_id, name=name, cancel_scope=self.cancel_scope + ) + self.cancel_scope._tasks.add(task) + return task + + def start_soon( + self, func: Callable[..., Coroutine], *args: object, name: object = None + ) -> None: + self._spawn(func, args, name) + + async def start( + self, func: Callable[..., Coroutine], *args: object, name: object = None + ) -> None: + 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. + with CancelScope(shield=True): + try: + return await future + except CancelledError: + task.cancel() + 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[ + Union[Tuple[Context, Callable, tuple, asyncio.Future], None] + ] = Queue(2) + self.idle_since = current_time() + self.stopping = False + + def _report_result( + self, future: asyncio.Future, result: Any, exc: Optional[BaseException] + ) -> None: + self.idle_since = current_time() + if not self.stopping: + self.idle_workers.append(self) + + if not future.cancelled(): + if exc is not None: + future.set_exception(exc) + else: + future.set_result(result) + + def run(self) -> None: + with claim_worker_thread("asyncio"): + threadlocals.loop = self.loop + while True: + item = self.queue.get() + if item is None: + # Shutdown command received + return + + context, func, args, future = item + if not future.cancelled(): + result = None + exception: Optional[BaseException] = None + try: + result = context.run(func, *args) + except BaseException as exc: + exception = exc + + if not self.loop.is_closed(): + self.loop.call_soon_threadsafe( + self._report_result, future, result, exception + ) + + self.queue.task_done() + + def stop(self, f: Optional[asyncio.Task] = 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") + + +async def run_sync_in_worker_thread( + func: Callable[..., T_Retval], + *args: object, + cancellable: bool = False, + limiter: Optional["CapacityLimiter"] = None, +) -> T_Retval: + await 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 current_default_thread_limiter()): + with CancelScope(shield=not cancellable): + future: asyncio.Future = asyncio.Future() + 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) + else: + worker = idle_workers.pop() + + # Prune any other workers that have been idle for MAX_IDLE_TIME seconds or longer + now = 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(sniffio.current_async_library_cvar.set, None) + worker.queue.put_nowait((context, func, args, future)) + return await future + + +def run_sync_from_thread( + func: Callable[..., T_Retval], + *args: object, + loop: Optional[asyncio.AbstractEventLoop] = None, +) -> T_Retval: + @wraps(func) + def wrapper() -> None: + try: + f.set_result(func(*args)) + except BaseException as exc: + f.set_exception(exc) + if not isinstance(exc, Exception): + raise + + f: concurrent.futures.Future[T_Retval] = Future() + loop = loop or threadlocals.loop + if sys.version_info < (3, 7): + loop.call_soon_threadsafe(copy_context().run, wrapper) + else: + loop.call_soon_threadsafe(wrapper) + + return f.result() + + +def run_async_from_thread( + func: Callable[..., Coroutine[Any, Any, T_Retval]], *args: object +) -> T_Retval: + f: concurrent.futures.Future[T_Retval] = asyncio.run_coroutine_threadsafe( + func(*args), threadlocals.loop + ) + return f.result() + + +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, + args: tuple, + kwargs: Dict[str, Any], + name: object, + future: Future, + ) -> None: + run_sync_from_thread( + partial(self._task_group.start_soon, name=name), + self._call_func, + func, + args, + kwargs, + future, + loop=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.feed_eof() + + +@dataclass(eq=False) +class StreamWriterWrapper(abc.ByteSendStream): + _stream: asyncio.StreamWriter + + async def send(self, item: bytes) -> None: + self._stream.write(item) + await self._stream.drain() + + async def aclose(self) -> None: + self._stream.close() + + +@dataclass(eq=False) +class Process(abc.Process): + _process: asyncio.subprocess.Process + _stdin: Optional[StreamWriterWrapper] + _stdout: Optional[StreamReaderWrapper] + _stderr: Optional[StreamReaderWrapper] + + async def aclose(self) -> None: + if self._stdin: + await self._stdin.aclose() + if self._stdout: + await self._stdout.aclose() + if self._stderr: + await self._stderr.aclose() + + await self.wait() + + 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) -> Optional[int]: + return self._process.returncode + + @property + def stdin(self) -> Optional[abc.ByteSendStream]: + return self._stdin + + @property + def stdout(self) -> Optional[abc.ByteReceiveStream]: + return self._stdout + + @property + def stderr(self) -> Optional[abc.ByteReceiveStream]: + return self._stderr + + +async def open_process( + command: Union[str, bytes, Sequence[Union[str, bytes]]], + *, + shell: bool, + stdin: Union[int, IO[Any], None], + stdout: Union[int, IO[Any], None], + stderr: Union[int, IO[Any], None], + cwd: Union[str, bytes, PathLike, None] = None, + env: Optional[Mapping[str, str]] = None, + start_new_session: bool = False, +) -> Process: + await checkpoint() + if shell: + process = await asyncio.create_subprocess_shell( + cast(Union[str, bytes], command), + stdin=stdin, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + start_new_session=start_new_session, + ) + else: + process = await asyncio.create_subprocess_exec( + *command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + start_new_session=start_new_session, + ) + + 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) + + +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: Optional[asyncio.AbstractChildWatcher] + try: + child_watcher = asyncio.get_event_loop_policy().get_child_watcher() + except NotImplementedError: + child_watcher = None + + # Close as much as possible (w/o async/await) to avoid warnings + for process in workers: + 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[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: Process + try: + await sleep(math.inf) + except asyncio.CancelledError: + for process in workers: + if process.returncode is None: + process.kill() + + for process in workers: + await process.aclose() + + +def setup_process_pool_exit_at_shutdown(workers: Set[Process]) -> None: + kwargs = {"name": "AnyIO process pool shutdown task"} if _native_task_names else {} + create_task(_shutdown_process_pool_on_exit(workers), **kwargs) + find_root_task().add_done_callback( + partial(_forcibly_shutdown_process_pool_on_exit, workers) + ) + + +# +# Sockets and networking +# + + +class StreamProtocol(asyncio.Protocol): + read_queue: Deque[bytes] + read_event: asyncio.Event + write_event: asyncio.Event + exception: Optional[Exception] = None + + 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: Optional[Exception]) -> 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: + self.read_queue.append(data) + self.read_event.set() + + def eof_received(self) -> Optional[bool]: + 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: Optional[Exception] = 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: Optional[Exception]) -> 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: + await checkpoint() + + if ( + not self._protocol.read_event.is_set() + and not self._transport.is_closing() + ): + self._transport.resume_reading() + await self._protocol.read_event.wait() + self._transport.pause_reading() + + try: + chunk = self._protocol.read_queue.popleft() + except IndexError: + if self._closed: + raise ClosedResourceError from None + elif self._protocol.exception: + raise self._protocol.exception + 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 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: + if not self._transport.is_closing(): + self._closed = True + try: + self._transport.write_eof() + except OSError: + pass + + self._transport.close() + await sleep(0) + self._transport.abort() + + +class UNIXSocketStream(abc.SocketStream): + _receive_future: Optional[asyncio.Future] = None + _send_future: Optional[asyncio.Future] = None + _closing = False + + def __init__(self, raw_socket: socket.socket): + self.__raw_socket = raw_socket + self._loop = get_running_loop() + 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() + self._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() + self._loop.add_writer(self.__raw_socket, f.set_result, None) + f.add_done_callback(callback) + return f + + 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 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 checkpoint() + with self._send_guard: + view = memoryview(item) + while view: + try: + bytes_sent = 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: + 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 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[Union[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 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 + + 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 TCPSocketListener(abc.SocketListener): + _accept_scope: Optional[CancelScope] = 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 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(cast(asyncio.Transport, 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 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: + if not self._transport.is_closing(): + self._closed = True + self._transport.close() + + async def receive(self) -> Tuple[bytes, IPSockAddrType]: + with self._receive_guard: + await 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 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: + if not self._transport.is_closing(): + self._closed = True + self._transport.close() + + async def receive(self) -> bytes: + with self._receive_guard: + await 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 checkpoint() + await self._protocol.write_event.wait() + if self._closed: + raise ClosedResourceError + elif self._transport.is_closing(): + raise BrokenResourceError + else: + self._transport.sendto(item) + + +async def connect_tcp( + host: str, port: int, local_addr: Optional[Tuple[str, int]] = None +) -> SocketStream: + transport, protocol = cast( + Tuple[asyncio.Transport, StreamProtocol], + await get_running_loop().create_connection( + StreamProtocol, host, port, local_addr=local_addr + ), + ) + transport.pause_reading() + return SocketStream(transport, protocol) + + +async def connect_unix(path: str) -> UNIXSocketStream: + await 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) + + +async def create_udp_socket( + family: socket.AddressFamily, + local_address: Optional[IPSockAddrType], + remote_address: Optional[IPSockAddrType], + reuse_port: bool, +) -> Union[UDPSocket, ConnectedUDPSocket]: + result = await get_running_loop().create_datagram_endpoint( + DatagramProtocol, + local_addr=local_address, + remote_addr=remote_address, + family=family, + reuse_port=reuse_port, + ) + transport = cast(asyncio.DatagramTransport, result[0]) + protocol = result[1] + if protocol.exception: + transport.close() + raise protocol.exception + + if not remote_address: + return UDPSocket(transport, protocol) + else: + return ConnectedUDPSocket(transport, protocol) + + +async def getaddrinfo( + host: Union[bytes, str], + port: Union[str, int, None], + *, + family: Union[int, AddressFamily] = 0, + type: Union[int, SocketKind] = 0, + proto: int = 0, + flags: int = 0, +) -> GetAddrInfoReturnType: + # https://github.com/python/typeshed/pull/4304 + result = await get_running_loop().getaddrinfo( + host, port, family=family, type=type, proto=proto, flags=flags + ) + return cast(GetAddrInfoReturnType, result) + + +async def getnameinfo(sockaddr: IPSockAddrType, flags: int = 0) -> Tuple[str, str]: + return await get_running_loop().getnameinfo(sockaddr, flags) + + +_read_events: RunVar[Dict[Any, asyncio.Event]] = RunVar("read_events") +_write_events: RunVar[Dict[Any, asyncio.Event]] = RunVar("write_events") + + +async def wait_socket_readable(sock: socket.socket) -> None: + await checkpoint() + try: + read_events = _read_events.get() + except LookupError: + read_events = {} + _read_events.set(read_events) + + if read_events.get(sock): + raise BusyResourceError("reading from") from None + + loop = get_running_loop() + event = read_events[sock] = asyncio.Event() + loop.add_reader(sock, event.set) + try: + await event.wait() + finally: + if read_events.pop(sock, None) is not None: + loop.remove_reader(sock) + readable = True + else: + readable = False + + if not readable: + raise ClosedResourceError + + +async def wait_socket_writable(sock: socket.socket) -> None: + await checkpoint() + try: + write_events = _write_events.get() + except LookupError: + write_events = {} + _write_events.set(write_events) + + if write_events.get(sock): + raise BusyResourceError("writing to") from None + + loop = get_running_loop() + event = write_events[sock] = asyncio.Event() + loop.add_writer(sock.fileno(), event.set) + try: + await event.wait() + finally: + if write_events.pop(sock, None) is not None: + loop.remove_writer(sock) + writable = True + else: + writable = False + + if not writable: + raise ClosedResourceError + + +# +# Synchronization +# + + +class Event(BaseEvent): + def __new__(cls) -> "Event": + return object.__new__(cls) + + def __init__(self) -> None: + self._event = asyncio.Event() + + def set(self) -> DeprecatedAwaitable: + self._event.set() + return DeprecatedAwaitable(self.set) + + def is_set(self) -> bool: + return self._event.is_set() + + async def wait(self) -> None: + if await self._event.wait(): + await checkpoint() + + def statistics(self) -> EventStatistics: + return EventStatistics(len(self._event._waiters)) # type: ignore[attr-defined] + + +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: Dict[Any, asyncio.Event] = OrderedDict() + self.total_tokens = total_tokens + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> 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 < 1: + raise ValueError("total_tokens must be >= 1") + + old_value = self._total_tokens + self._total_tokens = value + events = [] + for event in self._wait_queue.values(): + if value <= old_value: + break + + if not event.is_set(): + events.append(event) + old_value += 1 + + for event in events: + event.set() + + @property + def borrowed_tokens(self) -> int: + return len(self._borrowers) + + @property + def available_tokens(self) -> float: + return self._total_tokens - len(self._borrowers) + + def acquire_nowait(self) -> DeprecatedAwaitable: + self.acquire_on_behalf_of_nowait(current_task()) + return DeprecatedAwaitable(self.acquire_nowait) + + def acquire_on_behalf_of_nowait(self, borrower: object) -> DeprecatedAwaitable: + 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) + return DeprecatedAwaitable(self.acquire_on_behalf_of_nowait) + + 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 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) + raise + + self._borrowers.add(borrower) + else: + try: + await 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 + + # 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()[1] + event.set() + + 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") + + +def current_default_thread_limiter() -> CapacityLimiter: + try: + return _default_thread_limiter.get() + except LookupError: + limiter = CapacityLimiter(40) + _default_thread_limiter.set(limiter) + return limiter + + +# +# Operating system signals +# + + +class _SignalReceiver(DeprecatedAsyncContextManager["_SignalReceiver"]): + def __init__(self, signals: Tuple[int, ...]): + self._signals = signals + self._loop = get_running_loop() + self._signal_queue: Deque[int] = deque() + self._future: asyncio.Future = asyncio.Future() + self._handled_signals: Set[int] = set() + + def _deliver(self, signum: int) -> 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: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + for sig in self._handled_signals: + self._loop.remove_signal_handler(sig) + return None + + def __aiter__(self) -> "_SignalReceiver": + return self + + async def __anext__(self) -> int: + await checkpoint() + if not self._signal_queue: + self._future = asyncio.Future() + await self._future + + return self._signal_queue.popleft() + + +def open_signal_receiver(*signals: int) -> _SignalReceiver: + return _SignalReceiver(signals) + + +# +# Testing and debugging +# + + +def _create_task_info(task: asyncio.Task) -> TaskInfo: + task_state = _task_states.get(task) + if task_state is None: + name = task.get_name() if _native_task_names else None + parent_id = None + else: + name = task_state.name + parent_id = task_state.parent_id + + return TaskInfo(id(task), parent_id, name, get_coro(task)) + + +def get_current_task() -> TaskInfo: + return _create_task_info(current_task()) # type: ignore[arg-type] + + +def get_running_tasks() -> List[TaskInfo]: + return [_create_task_info(task) for task in all_tasks() if not task.done()] + + +async def wait_all_tasks_blocked() -> None: + await checkpoint() + this_task = current_task() + while True: + for task in all_tasks(): + if task is this_task: + continue + + if task._fut_waiter is None or task._fut_waiter.done(): # type: ignore[attr-defined] + await sleep(0.1) + break + else: + return + + +class TestRunner(abc.TestRunner): + def __init__( + self, + debug: bool = False, + use_uvloop: bool = False, + policy: Optional[asyncio.AbstractEventLoopPolicy] = None, + ): + self._exceptions: List[BaseException] = [] + _maybe_set_event_loop_policy(policy, use_uvloop) + self._loop = asyncio.new_event_loop() + self._loop.set_debug(debug) + self._loop.set_exception_handler(self._exception_handler) + asyncio.set_event_loop(self._loop) + + def _cancel_all_tasks(self) -> None: + to_cancel = all_tasks(self._loop) + if not to_cancel: + return + + for task in to_cancel: + task.cancel() + + self._loop.run_until_complete( + asyncio.gather(*to_cancel, return_exceptions=True) + ) + + for task in to_cancel: + if task.cancelled(): + continue + if task.exception() is not None: + raise cast(BaseException, task.exception()) + + 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 ExceptionGroup(exceptions) + + def close(self) -> None: + try: + self._cancel_all_tasks() + self._loop.run_until_complete(self._loop.shutdown_asyncgens()) + finally: + asyncio.set_event_loop(None) + self._loop.close() + + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], + kwargs: Dict[str, Any], + ) -> Iterable[T_Retval]: + async def fixture_runner() -> None: + agen = fixture_func(**kwargs) + try: + retval = await agen.asend(None) + self._raise_async_exceptions() + except BaseException as exc: + f.set_exception(exc) + return + else: + f.set_result(retval) + + await event.wait() + try: + await agen.asend(None) + except StopAsyncIteration: + pass + else: + await agen.aclose() + raise RuntimeError("Async generator fixture did not stop") + + f = self._loop.create_future() + event = asyncio.Event() + fixture_task = self._loop.create_task(fixture_runner()) + self._loop.run_until_complete(f) + yield f.result() + event.set() + self._loop.run_until_complete(fixture_task) + self._raise_async_exceptions() + + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], + kwargs: Dict[str, Any], + ) -> T_Retval: + retval = self._loop.run_until_complete(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._loop.run_until_complete(test_func(**kwargs)) + except Exception as exc: + self._exceptions.append(exc) + + self._raise_async_exceptions() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_trio.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_trio.py new file mode 100644 index 00000000..cf2aaece --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_backends/_trio.py @@ -0,0 +1,988 @@ +import array +import math +import socket +from concurrent.futures import Future +from contextvars import copy_context +from dataclasses import dataclass +from functools import partial +from io import IOBase +from os import PathLike +from signal import Signals +from types import TracebackType +from typing import ( + IO, + TYPE_CHECKING, + Any, + AsyncGenerator, + Awaitable, + Callable, + Collection, + ContextManager, + Coroutine, + Deque, + Dict, + Generic, + Iterable, + List, + Mapping, + NoReturn, + Optional, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, +) + +import sniffio +import trio.from_thread +from outcome import Error, Outcome, Value +from trio.socket import SocketType as TrioSocketType +from trio.to_thread import run_sync + +from .. import CapacityLimiterStatistics, EventStatistics, TaskInfo, abc +from .._core._compat import DeprecatedAsyncContextManager, DeprecatedAwaitable, T +from .._core._eventloop import claim_worker_thread +from .._core._exceptions import ( + BrokenResourceError, + BusyResourceError, + ClosedResourceError, + EndOfStream, +) +from .._core._exceptions import ExceptionGroup as BaseExceptionGroup +from .._core._sockets import convert_ipv6_sockaddr +from .._core._synchronization import CapacityLimiter as BaseCapacityLimiter +from .._core._synchronization import Event as BaseEvent +from .._core._synchronization import ResourceGuard +from .._core._tasks import CancelScope as BaseCancelScope +from ..abc import IPSockAddrType, UDPPacketType + +if TYPE_CHECKING: + from trio_typing import TaskStatus + +try: + from trio import lowlevel as trio_lowlevel +except ImportError: + from trio import hazmat as trio_lowlevel # type: ignore[no-redef] + from trio.hazmat import wait_readable, wait_writable +else: + from trio.lowlevel import wait_readable, wait_writable + +try: + trio_open_process = trio_lowlevel.open_process # type: ignore[attr-defined] +except AttributeError: + from trio import open_process as trio_open_process + +T_Retval = TypeVar("T_Retval") +T_SockAddr = TypeVar("T_SockAddr", str, IPSockAddrType) + + +# +# Event loop +# + +run = trio.run +current_token = trio.lowlevel.current_trio_token +RunVar = trio.lowlevel.RunVar + + +# +# Miscellaneous +# + +sleep = trio.sleep + + +# +# Timeouts and cancellation +# + + +class CancelScope(BaseCancelScope): + def __new__( + cls, original: Optional[trio.CancelScope] = None, **kwargs: object + ) -> "CancelScope": + return object.__new__(cls) + + def __init__( + self, original: Optional[trio.CancelScope] = 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: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + return self.__original.__exit__(exc_type, exc_val, exc_tb) + + def cancel(self) -> DeprecatedAwaitable: + self.__original.cancel() + return DeprecatedAwaitable(self.cancel) + + @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 shield(self) -> bool: + return self.__original.shield + + @shield.setter + def shield(self, value: bool) -> None: + self.__original.shield = value + + +CancelledError = trio.Cancelled +checkpoint = trio.lowlevel.checkpoint +checkpoint_if_cancelled = trio.lowlevel.checkpoint_if_cancelled +cancel_shielded_checkpoint = trio.lowlevel.cancel_shielded_checkpoint +current_effective_deadline = trio.current_effective_deadline +current_time = trio.current_time + + +# +# Task groups +# + + +class ExceptionGroup(BaseExceptionGroup, trio.MultiError): + pass + + +class TaskGroup(abc.TaskGroup): + def __init__(self) -> None: + self._active = False + self._nursery_manager = trio.open_nursery() + 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: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + try: + return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) + except trio.MultiError as exc: + raise ExceptionGroup(exc.exceptions) from None + finally: + self._active = False + + def start_soon(self, func: Callable, *args: object, 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[..., Coroutine], *args: object, name: object = None + ) -> object: + 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 +# + + +async def run_sync_in_worker_thread( + func: Callable[..., T_Retval], + *args: object, + cancellable: bool = False, + limiter: Optional[trio.CapacityLimiter] = None, +) -> T_Retval: + def wrapper() -> T_Retval: + with claim_worker_thread("trio"): + return func(*args) + + # TODO: remove explicit context copying when trio 0.20 is the minimum requirement + context = copy_context() + context.run(sniffio.current_async_library_cvar.set, None) + return await run_sync( + context.run, wrapper, cancellable=cancellable, limiter=limiter + ) + + +# TODO: remove this workaround when trio 0.20 is the minimum requirement +def run_async_from_thread( + fn: Callable[..., Awaitable[T_Retval]], *args: Any +) -> T_Retval: + async def wrapper() -> T_Retval: + retval: T_Retval + + async def inner() -> None: + nonlocal retval + __tracebackhide__ = True + retval = await fn(*args) + + async with trio.open_nursery() as n: + context.run(n.start_soon, inner) + + __tracebackhide__ = True + return retval + + context = copy_context() + context.run(sniffio.current_async_library_cvar.set, "trio") + return trio.from_thread.run(wrapper) + + +def run_sync_from_thread(fn: Callable[..., T_Retval], *args: Any) -> T_Retval: + # TODO: remove explicit context copying when trio 0.20 is the minimum requirement + retval = trio.from_thread.run_sync(copy_context().run, fn, *args) + return cast(T_Retval, retval) + + +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, + args: tuple, + kwargs: Dict[str, Any], + name: object, + future: Future, + ) -> None: + context = copy_context() + context.run(sniffio.current_async_library_cvar.set, "trio") + trio.from_thread.run_sync( + context.run, + 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: Optional[int] = 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 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: Optional[abc.ByteSendStream] + _stdout: Optional[abc.ByteReceiveStream] + _stderr: Optional[abc.ByteReceiveStream] + + async def aclose(self) -> None: + if self._stdin: + await self._stdin.aclose() + if self._stdout: + await self._stdout.aclose() + if self._stderr: + await self._stderr.aclose() + + await self.wait() + + 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) -> Optional[int]: + return self._process.returncode + + @property + def stdin(self) -> Optional[abc.ByteSendStream]: + return self._stdin + + @property + def stdout(self) -> Optional[abc.ByteReceiveStream]: + return self._stdout + + @property + def stderr(self) -> Optional[abc.ByteReceiveStream]: + return self._stderr + + +async def open_process( + command: Union[str, bytes, Sequence[Union[str, bytes]]], + *, + shell: bool, + stdin: Union[int, IO[Any], None], + stdout: Union[int, IO[Any], None], + stderr: Union[int, IO[Any], None], + cwd: Union[str, bytes, PathLike, None] = None, + env: Optional[Mapping[str, str]] = None, + start_new_session: bool = False, +) -> Process: + process = await trio_open_process( + command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + shell=shell, + cwd=cwd, + env=env, + start_new_session=start_new_session, + ) + 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) + + +class _ProcessPoolShutdownInstrument(trio.abc.Instrument): + def after_run(self) -> None: + super().after_run() + + +current_default_worker_process_limiter: RunVar = RunVar( + "current_default_worker_process_limiter" +) + + +async def _shutdown_process_pool(workers: Set[Process]) -> None: + process: Process + try: + await 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() + + +def setup_process_pool_exit_at_shutdown(workers: Set[Process]) -> None: + trio.lowlevel.spawn_system_task(_shutdown_process_pool, workers) + + +# +# 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 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[Union[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 checkpoint() + with self._send_guard: + while True: + try: + await self._trio_socket.sendmsg( + [message], + [ + ( + socket.SOL_SOCKET, + socket.SCM_RIGHTS, # type: ignore[list-item] + 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) + + +async def connect_tcp( + host: str, port: int, local_address: Optional[IPSockAddrType] = 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) + + +async def connect_unix(path: str) -> 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) + + +async def create_udp_socket( + family: socket.AddressFamily, + local_address: Optional[IPSockAddrType], + remote_address: Optional[IPSockAddrType], + reuse_port: bool, +) -> Union[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) + + +getaddrinfo = trio.socket.getaddrinfo +getnameinfo = trio.socket.getnameinfo + + +async def wait_socket_readable(sock: socket.socket) -> None: + try: + await wait_readable(sock) + except trio.ClosedResourceError as exc: + raise ClosedResourceError().with_traceback(exc.__traceback__) from None + except trio.BusyResourceError: + raise BusyResourceError("reading from") from None + + +async def wait_socket_writable(sock: socket.socket) -> None: + try: + await wait_writable(sock) + except trio.ClosedResourceError as exc: + raise ClosedResourceError().with_traceback(exc.__traceback__) from None + except trio.BusyResourceError: + raise BusyResourceError("writing to") from None + + +# +# 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) -> DeprecatedAwaitable: + self.__original.set() + return DeprecatedAwaitable(self.set) + + +class CapacityLimiter(BaseCapacityLimiter): + def __new__(cls, *args: object, **kwargs: object) -> "CapacityLimiter": + return object.__new__(cls) + + def __init__( + self, *args: Any, original: Optional[trio.CapacityLimiter] = None + ) -> None: + self.__original = original or trio.CapacityLimiter(*args) + + async def __aenter__(self) -> None: + return await self.__original.__aenter__() + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + return 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) -> DeprecatedAwaitable: + self.__original.acquire_nowait() + return DeprecatedAwaitable(self.acquire_nowait) + + def acquire_on_behalf_of_nowait(self, borrower: object) -> DeprecatedAwaitable: + self.__original.acquire_on_behalf_of_nowait(borrower) + return DeprecatedAwaitable(self.acquire_on_behalf_of_nowait) + + 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=orig.borrowers, + tasks_waiting=orig.tasks_waiting, + ) + + +_capacity_limiter_wrapper: RunVar = RunVar("_capacity_limiter_wrapper") + + +def current_default_thread_limiter() -> 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 + + +# +# Signal handling +# + + +class _SignalReceiver(DeprecatedAsyncContextManager[T]): + def __init__(self, cm: ContextManager[T]): + self._cm = cm + + def __enter__(self) -> T: + return self._cm.__enter__() + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + return self._cm.__exit__(exc_type, exc_val, exc_tb) + + +def open_signal_receiver(*signals: Signals) -> _SignalReceiver: + cm = trio.open_signal_receiver(*signals) + return _SignalReceiver(cm) + + +# +# Testing and debugging +# + + +def get_current_task() -> TaskInfo: + task = trio_lowlevel.current_task() + + parent_id = None + if task.parent_nursery and task.parent_nursery.parent_task: + parent_id = id(task.parent_nursery.parent_task) + + return TaskInfo(id(task), parent_id, task.name, task.coro) + + +def get_running_tasks() -> List[TaskInfo]: + root_task = trio_lowlevel.current_root_task() + task_infos = [TaskInfo(id(root_task), None, root_task.name, root_task.coro)] + 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( + TaskInfo(id(task), id(nursery.parent_task), task.name, task.coro) + ) + new_nurseries.extend(task.child_nurseries) + + nurseries = new_nurseries + + return task_infos + + +def wait_all_tasks_blocked() -> Awaitable[None]: + import trio.testing + + return trio.testing.wait_all_tasks_blocked() + + +class TestRunner(abc.TestRunner): + def __init__(self, **options: Any) -> None: + from collections import deque + from queue import Queue + + self._call_queue: "Queue[Callable[..., object]]" = Queue() + self._result_queue: Deque[Outcome] = deque() + self._stop_event: Optional[trio.Event] = None + self._nursery: Optional[trio.Nursery] = None + self._options = options + + async def _trio_main(self) -> None: + self._stop_event = trio.Event() + async with trio.open_nursery() as self._nursery: + await self._stop_event.wait() + + async def _call_func( + self, func: Callable[..., Awaitable[object]], args: tuple, kwargs: dict + ) -> None: + try: + retval = await func(*args, **kwargs) + except BaseException as exc: + self._result_queue.append(Error(exc)) + else: + self._result_queue.append(Value(retval)) + + def _main_task_finished(self, outcome: object) -> None: + self._nursery = None + + def _get_nursery(self) -> trio.Nursery: + if self._nursery is None: + trio.lowlevel.start_guest_run( + self._trio_main, + run_sync_soon_threadsafe=self._call_queue.put, + done_callback=self._main_task_finished, + **self._options, + ) + while self._nursery is None: + self._call_queue.get()() + + return self._nursery + + def _call( + self, func: Callable[..., Awaitable[T_Retval]], *args: object, **kwargs: object + ) -> T_Retval: + self._get_nursery().start_soon(self._call_func, func, args, kwargs) + while not self._result_queue: + self._call_queue.get()() + + outcome = self._result_queue.pop() + return outcome.unwrap() + + def close(self) -> None: + if self._stop_event: + self._stop_event.set() + while self._nursery is not None: + self._call_queue.get()() + + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], + kwargs: Dict[str, Any], + ) -> Iterable[T_Retval]: + async def fixture_runner(*, task_status: "TaskStatus") -> None: + agen = fixture_func(**kwargs) + retval = await agen.asend(None) + task_status.started(retval) + await teardown_event.wait() + try: + await agen.asend(None) + except StopAsyncIteration: + pass + else: + await agen.aclose() + raise RuntimeError("Async generator fixture did not stop") + + teardown_event = trio.Event() + fixture_value = self._call(lambda: self._get_nursery().start(fixture_runner)) + yield fixture_value + teardown_event.set() + + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], + kwargs: Dict[str, Any], + ) -> T_Retval: + return self._call(fixture_func, **kwargs) + + def run_test( + self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: Dict[str, Any] + ) -> None: + self._call(test_func, **kwargs) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_compat.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_compat.py new file mode 100644 index 00000000..7062be5d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_compat.py @@ -0,0 +1,218 @@ +from abc import ABCMeta, abstractmethod +from contextlib import AbstractContextManager +from types import TracebackType +from typing import ( + TYPE_CHECKING, + Any, + AsyncContextManager, + Callable, + ContextManager, + Generator, + Generic, + Iterable, + List, + Optional, + Tuple, + Type, + TypeVar, + Union, + overload, +) +from warnings import warn + +if TYPE_CHECKING: + from ._testing import TaskInfo +else: + TaskInfo = object + +T = TypeVar("T") +AnyDeprecatedAwaitable = Union[ + "DeprecatedAwaitable", + "DeprecatedAwaitableFloat", + "DeprecatedAwaitableList[T]", + TaskInfo, +] + + +@overload +async def maybe_async(__obj: TaskInfo) -> TaskInfo: + ... + + +@overload +async def maybe_async(__obj: "DeprecatedAwaitableFloat") -> float: + ... + + +@overload +async def maybe_async(__obj: "DeprecatedAwaitableList[T]") -> List[T]: + ... + + +@overload +async def maybe_async(__obj: "DeprecatedAwaitable") -> None: + ... + + +async def maybe_async( + __obj: "AnyDeprecatedAwaitable[T]", +) -> Union[TaskInfo, float, List[T], None]: + """ + Await on the given object if necessary. + + This function is intended to bridge the gap between AnyIO 2.x and 3.x where some functions and + methods were converted from coroutine functions into regular functions. + + Do **not** try to use this for any other purpose! + + :return: the result of awaiting on the object if coroutine, or the object itself otherwise + + .. versionadded:: 2.2 + + """ + return __obj._unwrap() + + +class _ContextManagerWrapper: + def __init__(self, cm: ContextManager[T]): + self._cm = cm + + async def __aenter__(self) -> T: + return self._cm.__enter__() + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + return self._cm.__exit__(exc_type, exc_val, exc_tb) + + +def maybe_async_cm( + cm: Union[ContextManager[T], AsyncContextManager[T]] +) -> AsyncContextManager[T]: + """ + Wrap a regular context manager as an async one if necessary. + + This function is intended to bridge the gap between AnyIO 2.x and 3.x where some functions and + methods were changed to return regular context managers instead of async ones. + + :param cm: a regular or async context manager + :return: an async context manager + + .. versionadded:: 2.2 + + """ + if not isinstance(cm, AbstractContextManager): + raise TypeError("Given object is not an context manager") + + return _ContextManagerWrapper(cm) + + +def _warn_deprecation( + awaitable: "AnyDeprecatedAwaitable[Any]", stacklevel: int = 1 +) -> None: + warn( + f'Awaiting on {awaitable._name}() is deprecated. Use "await ' + f"anyio.maybe_async({awaitable._name}(...)) if you have to support both AnyIO 2.x " + f'and 3.x, or just remove the "await" if you are completely migrating to AnyIO 3+.', + DeprecationWarning, + stacklevel=stacklevel + 1, + ) + + +class DeprecatedAwaitable: + def __init__(self, func: Callable[..., "DeprecatedAwaitable"]): + self._name = f"{func.__module__}.{func.__qualname__}" + + def __await__(self) -> Generator[None, None, None]: + _warn_deprecation(self) + if False: + yield + + def __reduce__(self) -> Tuple[Type[None], Tuple[()]]: + return type(None), () + + def _unwrap(self) -> None: + return None + + +class DeprecatedAwaitableFloat(float): + def __new__( + cls, x: float, func: Callable[..., "DeprecatedAwaitableFloat"] + ) -> "DeprecatedAwaitableFloat": + return super().__new__(cls, x) + + def __init__(self, x: float, func: Callable[..., "DeprecatedAwaitableFloat"]): + self._name = f"{func.__module__}.{func.__qualname__}" + + def __await__(self) -> Generator[None, None, float]: + _warn_deprecation(self) + if False: + yield + + return float(self) + + def __reduce__(self) -> Tuple[Type[float], Tuple[float]]: + return float, (float(self),) + + def _unwrap(self) -> float: + return float(self) + + +class DeprecatedAwaitableList(List[T]): + def __init__( + self, + iterable: Iterable[T] = (), + *, + func: Callable[..., "DeprecatedAwaitableList[T]"], + ): + super().__init__(iterable) + self._name = f"{func.__module__}.{func.__qualname__}" + + def __await__(self) -> Generator[None, None, List[T]]: + _warn_deprecation(self) + if False: + yield + + return list(self) + + def __reduce__(self) -> Tuple[Type[List[T]], Tuple[List[T]]]: + return list, (list(self),) + + def _unwrap(self) -> List[T]: + return list(self) + + +class DeprecatedAsyncContextManager(Generic[T], metaclass=ABCMeta): + @abstractmethod + def __enter__(self) -> T: + pass + + @abstractmethod + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + pass + + async def __aenter__(self) -> T: + warn( + f"Using {self.__class__.__name__} as an async context manager has been deprecated. " + f'Use "async with anyio.maybe_async_cm(yourcontextmanager) as foo:" if you have to ' + f'support both AnyIO 2.x and 3.x, or just remove the "async" from "async with" if ' + f"you are completely migrating to AnyIO 3+.", + DeprecationWarning, + ) + return self.__enter__() + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + return self.__exit__(exc_type, exc_val, exc_tb) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_eventloop.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_eventloop.py new file mode 100644 index 00000000..f027ae50 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_eventloop.py @@ -0,0 +1,155 @@ +import math +import sys +import threading +from contextlib import contextmanager +from importlib import import_module +from typing import ( + Any, + Callable, + Coroutine, + Dict, + Generator, + Optional, + Tuple, + Type, + TypeVar, +) + +import sniffio + +# This must be updated when new backends are introduced +from ._compat import DeprecatedAwaitableFloat + +BACKENDS = "asyncio", "trio" + +T_Retval = TypeVar("T_Retval") +threadlocals = threading.local() + + +def run( + func: Callable[..., Coroutine[Any, Any, T_Retval]], + *args: object, + backend: str = "asyncio", + backend_options: Optional[Dict[str, Any]] = 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 + + """ + try: + asynclib_name = sniffio.current_async_library() + except sniffio.AsyncLibraryNotFoundError: + pass + else: + raise RuntimeError(f"Already running {asynclib_name} in this thread") + + try: + asynclib = import_module(f"..._backends._{backend}", package=__name__) + except ImportError as exc: + raise LookupError(f"No such backend: {backend}") from exc + + token = None + if sniffio.current_async_library_cvar.get(None) is None: + # Since we're in control of the event loop, we can cache the name of the async library + token = sniffio.current_async_library_cvar.set(backend) + + try: + backend_options = backend_options or {} + return asynclib.run(func, *args, **backend_options) + finally: + if token: + sniffio.current_async_library_cvar.reset(token) + + +async def sleep(delay: float) -> None: + """ + Pause the current task for the specified duration. + + :param delay: the duration, in seconds + + """ + return await get_asynclib().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() -> DeprecatedAwaitableFloat: + """ + Return the current value of the event loop's internal clock. + + :return: the clock value (seconds) + + """ + return DeprecatedAwaitableFloat(get_asynclib().current_time(), current_time) + + +def get_all_backends() -> Tuple[str, ...]: + """Return a tuple of the names of all built-in backends.""" + return BACKENDS + + +def get_cancelled_exc_class() -> Type[BaseException]: + """Return the current async library's cancellation exception class.""" + return get_asynclib().CancelledError + + +# +# Private API +# + + +@contextmanager +def claim_worker_thread(backend: str) -> Generator[Any, None, None]: + module = sys.modules["anyio._backends._" + backend] + threadlocals.current_async_module = module + try: + yield + finally: + del threadlocals.current_async_module + + +def get_asynclib(asynclib_name: Optional[str] = None) -> Any: + if asynclib_name is None: + asynclib_name = sniffio.current_async_library() + + modulename = "anyio._backends._" + asynclib_name + try: + return sys.modules[modulename] + except KeyError: + return import_module(modulename) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_exceptions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_exceptions.py new file mode 100644 index 00000000..db2bbcf5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_exceptions.py @@ -0,0 +1,93 @@ +from traceback import format_exception +from typing import List + + +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 :func:`run_sync_in_process` if the worker process terminates abruptly or otherwise + misbehaves. + """ + + +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 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 ExceptionGroup(BaseException): + """ + Raised when multiple exceptions have been raised in a task group. + + :var ~typing.Sequence[BaseException] exceptions: the sequence of exceptions raised together + """ + + SEPARATOR = "----------------------------\n" + + exceptions: List[BaseException] + + def __str__(self) -> str: + tracebacks = [ + "".join(format_exception(type(exc), exc, exc.__traceback__)) + for exc in self.exceptions + ] + return ( + f"{len(self.exceptions)} exceptions were raised in the task group:\n" + f"{self.SEPARATOR}{self.SEPARATOR.join(tracebacks)}" + ) + + def __repr__(self) -> str: + exception_reprs = ", ".join(repr(exc) for exc in self.exceptions) + return f"<{self.__class__.__name__}: {exception_reprs}>" + + +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.""" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_fileio.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_fileio.py new file mode 100644 index 00000000..19c1e834 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_fileio.py @@ -0,0 +1,607 @@ +import os +import pathlib +import sys +from dataclasses import dataclass +from functools import partial +from os import PathLike +from typing import ( + IO, + TYPE_CHECKING, + Any, + AnyStr, + AsyncIterator, + Callable, + Generic, + Iterable, + Iterator, + List, + Optional, + Sequence, + Tuple, + Union, + cast, + overload, +) + +from .. import to_thread +from ..abc import AsyncResource + +if sys.version_info >= (3, 8): + from typing import Final +else: + from typing_extensions import Final + +if TYPE_CHECKING: + 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) -> bytes: + return await to_thread.run_sync(self._fp.readinto, b) + + async def readinto1(self: "AsyncFile[bytes]", b: WriteableBuffer) -> bytes: + 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: Union[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: Union[Iterable[ReadableBuffer], Iterable[str]] + ) -> None: + return await to_thread.run_sync(self._fp.writelines, lines) + + async def truncate(self, size: Optional[int] = None) -> int: + return await to_thread.run_sync(self._fp.truncate, size) + + async def seek(self, offset: int, whence: Optional[int] = 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: Union[str, "PathLike[str]", int], + mode: OpenBinaryMode, + buffering: int = ..., + encoding: Optional[str] = ..., + errors: Optional[str] = ..., + newline: Optional[str] = ..., + closefd: bool = ..., + opener: Optional[Callable[[str, int], int]] = ..., +) -> AsyncFile[bytes]: + ... + + +@overload +async def open_file( + file: Union[str, "PathLike[str]", int], + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: Optional[str] = ..., + errors: Optional[str] = ..., + newline: Optional[str] = ..., + closefd: bool = ..., + opener: Optional[Callable[[str, int], int]] = ..., +) -> AsyncFile[str]: + ... + + +async def open_file( + file: Union[str, "PathLike[str]", int], + mode: str = "r", + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + closefd: bool = True, + opener: Optional[Callable[[str, int], int]] = 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, cancellable=True) + if nextval is None: + raise StopAsyncIteration from None + + return Path(cast("PathLike[str]", 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. + + 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_mount` + * :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.rmdir` + * :meth:`~pathlib.Path.samefile` + * :meth:`~pathlib.Path.stat` + * :meth:`~pathlib.Path.touch` + * :meth:`~pathlib.Path.unlink` + * :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: Union[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: "Path") -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__lt__(target) + + def __le__(self, other: "Path") -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__le__(target) + + def __gt__(self, other: "Path") -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__gt__(target) + + def __ge__(self, other: "Path") -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__ge__(target) + + def __truediv__(self, other: Any) -> "Path": + return Path(self._path / other) + + def __rtruediv__(self, other: Any) -> "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() + + def match(self, path_pattern: str) -> bool: + return self._path.match(path_pattern) + + def is_relative_to(self, *other: Union[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, cancellable=True) + + async def expanduser(self) -> "Path": + return Path(await to_thread.run_sync(self._path.expanduser, cancellable=True)) + + def glob(self, pattern: str) -> AsyncIterator["Path"]: + gen = self._path.glob(pattern) + return _PathIterator(gen) + + async def group(self) -> str: + return await to_thread.run_sync(self._path.group, cancellable=True) + + async def hardlink_to(self, target: Union[str, pathlib.Path, "Path"]) -> 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, cancellable=True) + + async def is_char_device(self) -> bool: + return await to_thread.run_sync(self._path.is_char_device, cancellable=True) + + async def is_dir(self) -> bool: + return await to_thread.run_sync(self._path.is_dir, cancellable=True) + + async def is_fifo(self) -> bool: + return await to_thread.run_sync(self._path.is_fifo, cancellable=True) + + async def is_file(self) -> bool: + return await to_thread.run_sync(self._path.is_file, cancellable=True) + + async def is_mount(self) -> bool: + return await to_thread.run_sync(os.path.ismount, self._path, cancellable=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, cancellable=True) + + async def is_symlink(self) -> bool: + return await to_thread.run_sync(self._path.is_symlink, cancellable=True) + + def iterdir(self) -> AsyncIterator["Path"]: + gen = self._path.iterdir() + return _PathIterator(gen) + + def joinpath(self, *args: Union[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, cancellable=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: Optional[str] = ..., + errors: Optional[str] = ..., + newline: Optional[str] = ..., + ) -> AsyncFile[bytes]: + ... + + @overload + async def open( + self, + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: Optional[str] = ..., + errors: Optional[str] = ..., + newline: Optional[str] = ..., + ) -> AsyncFile[str]: + ... + + async def open( + self, + mode: str = "r", + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = 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, cancellable=True) + + async def read_bytes(self) -> bytes: + return await to_thread.run_sync(self._path.read_bytes) + + async def read_text( + self, encoding: Optional[str] = None, errors: Optional[str] = None + ) -> str: + return await to_thread.run_sync(self._path.read_text, encoding, errors) + + def relative_to(self, *other: Union[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(cast(str, target)) + + async def rename(self, target: Union[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: Union[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, cancellable=True)) + + def rglob(self, pattern: str) -> AsyncIterator["Path"]: + gen = self._path.rglob(pattern) + return _PathIterator(gen) + + async def rmdir(self) -> None: + await to_thread.run_sync(self._path.rmdir) + + async def samefile( + self, other_path: Union[str, bytes, int, pathlib.Path, "Path"] + ) -> bool: + if isinstance(other_path, Path): + other_path = other_path._path + + return await to_thread.run_sync( + self._path.samefile, other_path, cancellable=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, cancellable=True) + + async def symlink_to( + self, + target: Union[str, pathlib.Path, "Path"], + 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 + + 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)) + + 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: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_resources.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_resources.py new file mode 100644 index 00000000..b9414f7b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_resources.py @@ -0,0 +1,16 @@ +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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_signals.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_signals.py new file mode 100644 index 00000000..02234fd2 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_signals.py @@ -0,0 +1,24 @@ +from typing import AsyncIterator + +from ._compat import DeprecatedAsyncContextManager +from ._eventloop import get_asynclib + + +def open_signal_receiver( + *signals: int, +) -> DeprecatedAsyncContextManager[AsyncIterator[int]]: + """ + 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_asynclib().open_signal_receiver(*signals) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_sockets.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_sockets.py new file mode 100644 index 00000000..ca85d30f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_sockets.py @@ -0,0 +1,587 @@ +import socket +import ssl +import sys +from ipaddress import IPv6Address, ip_address +from os import PathLike, chmod +from pathlib import Path +from socket import AddressFamily, SocketKind +from typing import Awaitable, List, Optional, Tuple, Union, cast, overload + +from .. import to_thread +from ..abc import ( + ConnectedUDPSocket, + IPAddressType, + IPSockAddrType, + SocketListener, + SocketStream, + UDPSocket, + UNIXSocketStream, +) +from ..streams.stapled import MultiListener +from ..streams.tls import TLSStream +from ._eventloop import get_asynclib +from ._resources import aclose_forcefully +from ._synchronization import Event +from ._tasks import create_task_group, move_on_after + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal + +IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) # https://bugs.python.org/issue29515 + +GetAddrInfoReturnType = List[ + Tuple[AddressFamily, SocketKind, int, str, Tuple[str, int]] +] +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: Optional[IPAddressType] = ..., + ssl_context: Optional[ssl.SSLContext] = ..., + 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: Optional[IPAddressType] = ..., + ssl_context: ssl.SSLContext, + tls_standard_compatible: bool = ..., + tls_hostname: Optional[str] = ..., + happy_eyeballs_delay: float = ..., +) -> TLSStream: + ... + + +# tls=True +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: Optional[IPAddressType] = ..., + tls: Literal[True], + ssl_context: Optional[ssl.SSLContext] = ..., + tls_standard_compatible: bool = ..., + tls_hostname: Optional[str] = ..., + happy_eyeballs_delay: float = ..., +) -> TLSStream: + ... + + +# tls=False +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: Optional[IPAddressType] = ..., + tls: Literal[False], + ssl_context: Optional[ssl.SSLContext] = ..., + tls_standard_compatible: bool = ..., + tls_hostname: Optional[str] = ..., + happy_eyeballs_delay: float = ..., +) -> SocketStream: + ... + + +# No TLS arguments +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: Optional[IPAddressType] = ..., + happy_eyeballs_delay: float = ..., +) -> SocketStream: + ... + + +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: Optional[IPAddressType] = None, + tls: bool = False, + ssl_context: Optional[ssl.SSLContext] = None, + tls_standard_compatible: bool = True, + tls_hostname: Optional[str] = None, + happy_eyeballs_delay: float = 0.25, +) -> Union[SocketStream, TLSStream]: + """ + Connect to a host using the TCP protocol. + + This function implements the stateless version of the Happy Eyeballs algorithm (RFC 6555). + If ``address`` 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 OSError: if the connection attempt fails + + """ + # Placed here due to https://github.com/python/mypy/issues/7057 + connected_stream: Optional[SocketStream] = 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_asynclib() + local_address: Optional[IPSockAddrType] = 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: + # 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: List[Tuple[socket.AddressFamily, str]] = [] + for af, *rest, 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])) + else: + if isinstance(addr_obj, IPv6Address): + target_addrs = [(socket.AF_INET6, addr_obj.compressed)] + else: + target_addrs = [(socket.AF_INET, addr_obj.compressed)] + + oserrors: List[OSError] = [] + async with create_task_group() as tg: + for i, (af, addr) in enumerate(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 asynclib.ExceptionGroup(oserrors) + raise OSError("All connection attempts failed") from cause + + 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: Union[str, "PathLike[str]"]) -> UNIXSocketStream: + """ + Connect to the given UNIX socket. + + Not available on Windows. + + :param path: path to the socket + :return: a socket stream object + + """ + path = str(Path(path)) + return await get_asynclib().connect_unix(path) + + +async def create_tcp_listener( + *, + local_host: Optional[IPAddressType] = 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 ``interface`` 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 list of listener objects + + """ + asynclib = get_asynclib() + backlog = min(backlog, 65536) + local_host = str(local_host) if local_host is not None else None + gai_res = await getaddrinfo( + local_host, # type: ignore[arg-type] + local_port, + family=family, + type=socket.SOCK_STREAM, + flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, + ) + listeners: List[SocketListener] = [] + try: + # The set() is here to work around a glibc bug: + # https://sourceware.org/bugzilla/show_bug.cgi?id=14969 + for fam, *_, sockaddr in sorted(set(gai_res)): + raw_socket = socket.socket(fam) + raw_socket.setblocking(False) + + # For Windows, enable exclusive address use. For others, enable address reuse. + if sys.platform == "win32": + raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) + else: + raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + if reuse_port: + raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + + # If only IPv6 was requested, disable dual stack operation + if fam == socket.AF_INET6: + raw_socket.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) + + raw_socket.bind(sockaddr) + raw_socket.listen(backlog) + listener = asynclib.TCPSocketListener(raw_socket) + listeners.append(listener) + except BaseException: + for listener in listeners: + await listener.aclose() + + raise + + return MultiListener(listeners) + + +async def create_unix_listener( + path: Union[str, "PathLike[str]"], + *, + mode: Optional[int] = 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. + + """ + path_str = str(path) + path = Path(path) + if path.is_socket(): + path.unlink() + + backlog = min(backlog, 65536) + raw_socket = socket.socket(socket.AF_UNIX) + raw_socket.setblocking(False) + try: + await to_thread.run_sync(raw_socket.bind, path_str, cancellable=True) + if mode is not None: + await to_thread.run_sync(chmod, path_str, mode, cancellable=True) + + raw_socket.listen(backlog) + return get_asynclib().UNIXSocketListener(raw_socket) + except BaseException: + raw_socket.close() + raise + + +async def create_udp_socket( + family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, + *, + local_host: Optional[IPAddressType] = 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) + + return await get_asynclib().create_udp_socket( + family, local_address, None, reuse_port + ) + + +async def create_connected_udp_socket( + remote_host: IPAddressType, + remote_port: int, + *, + family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, + local_host: Optional[IPAddressType] = 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, and 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] + + return await get_asynclib().create_udp_socket( + family, local_address, remote_address, reuse_port + ) + + +async def getaddrinfo( + host: Union[bytearray, bytes, str], + port: Union[str, int, None], + *, + family: Union[int, AddressFamily] = 0, + type: Union[int, SocketKind] = 0, + proto: int = 0, + flags: int = 0, +) -> GetAddrInfoReturnType: + """ + 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 = host.encode("ascii") + except UnicodeEncodeError: + import idna + + encoded_host = idna.encode(host, uts46=True) + else: + encoded_host = host + + gai_res = await get_asynclib().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 + ] + + +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_asynclib().getnameinfo(sockaddr, flags) + + +def wait_socket_readable(sock: socket.socket) -> Awaitable[None]: + """ + Wait until the given socket has data to be read. + + 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 readable + :raises ~anyio.BusyResourceError: if another task is already waiting for the socket + to become readable + + """ + return get_asynclib().wait_socket_readable(sock) + + +def wait_socket_writable(sock: socket.socket) -> Awaitable[None]: + """ + 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_asynclib().wait_socket_writable(sock) + + +# +# Private API +# + + +def convert_ipv6_sockaddr( + sockaddr: Union[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 = cast(Tuple[str, int, int, int], sockaddr) + if scope_id: + # Add scope_id to the address + return f"{host}%{scope_id}", port + else: + return host, port + else: + return cast(Tuple[str, int], sockaddr) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_streams.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_streams.py new file mode 100644 index 00000000..58954a68 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_streams.py @@ -0,0 +1,45 @@ +import math +from typing import Any, Optional, Tuple, Type, TypeVar, overload + +from ..streams.memory import ( + MemoryObjectReceiveStream, + MemoryObjectSendStream, + MemoryObjectStreamState, +) + +T_Item = TypeVar("T_Item") + + +@overload +def create_memory_object_stream( + max_buffer_size: float, item_type: Type[T_Item] +) -> Tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]]: + ... + + +@overload +def create_memory_object_stream( + max_buffer_size: float = 0, +) -> Tuple[MemoryObjectSendStream[Any], MemoryObjectReceiveStream[Any]]: + ... + + +def create_memory_object_stream( + max_buffer_size: float = 0, item_type: Optional[Type[T_Item]] = None +) -> Tuple[MemoryObjectSendStream[Any], MemoryObjectReceiveStream[Any]]: + """ + Create a memory object stream. + + :param max_buffer_size: number of items held in the buffer until ``send()`` starts blocking + :param item_type: type of item, for marking the streams with the right generic type for + static typing (not used at run time) + :return: a tuple of (send stream, receive stream) + + """ + 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") + + state: MemoryObjectStreamState = MemoryObjectStreamState(max_buffer_size) + return MemoryObjectSendStream(state), MemoryObjectReceiveStream(state) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_subprocesses.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_subprocesses.py new file mode 100644 index 00000000..43fa6b6f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_subprocesses.py @@ -0,0 +1,136 @@ +from io import BytesIO +from os import PathLike +from subprocess import DEVNULL, PIPE, CalledProcessError, CompletedProcess +from typing import ( + IO, + Any, + AsyncIterable, + List, + Mapping, + Optional, + Sequence, + Union, + cast, +) + +from ..abc import Process +from ._eventloop import get_asynclib +from ._tasks import create_task_group + + +async def run_process( + command: Union[str, bytes, Sequence[Union[str, bytes]]], + *, + input: Optional[bytes] = None, + stdout: Union[int, IO[Any], None] = PIPE, + stderr: Union[int, IO[Any], None] = PIPE, + check: bool = True, + cwd: Union[str, bytes, "PathLike[str]", None] = None, + env: Optional[Mapping[str, str]] = None, + start_new_session: bool = False, +) -> "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 stdout: either :data:`subprocess.PIPE` or :data:`subprocess.DEVNULL` + :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL` or + :data:`subprocess.STDOUT` + :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 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) + :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() + + async with await open_process( + command, + stdin=PIPE if input else DEVNULL, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + start_new_session=start_new_session, + ) as process: + stream_contents: List[Optional[bytes]] = [None, None] + try: + 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() + except BaseException: + process.kill() + raise + + 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: Union[str, bytes, Sequence[Union[str, bytes]]], + *, + stdin: Union[int, IO[Any], None] = PIPE, + stdout: Union[int, IO[Any], None] = PIPE, + stderr: Union[int, IO[Any], None] = PIPE, + cwd: Union[str, bytes, "PathLike[str]", None] = None, + env: Optional[Mapping[str, str]] = None, + start_new_session: bool = False, +) -> 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 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) + :return: an asynchronous process object + + """ + shell = isinstance(command, str) + return await get_asynclib().open_process( + command, + shell=shell, + stdin=stdin, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + start_new_session=start_new_session, + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_synchronization.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_synchronization.py new file mode 100644 index 00000000..15d4afcd --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_synchronization.py @@ -0,0 +1,595 @@ +from collections import deque +from dataclasses import dataclass +from types import TracebackType +from typing import Deque, Optional, Tuple, Type +from warnings import warn + +from ..lowlevel import cancel_shielded_checkpoint, checkpoint, checkpoint_if_cancelled +from ._compat import DeprecatedAwaitable +from ._eventloop import get_asynclib +from ._exceptions import BusyResourceError, WouldBlock +from ._tasks import CancelScope +from ._testing import TaskInfo, get_current_task + + +@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: Optional[TaskInfo] + 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": + return get_asynclib().Event() + + def set(self) -> DeprecatedAwaitable: + """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 Lock: + _owner_task: Optional[TaskInfo] = None + + def __init__(self) -> None: + self._waiters: Deque[Tuple[TaskInfo, Event]] = deque() + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.release() + + async def acquire(self) -> None: + """Acquire the lock.""" + await checkpoint_if_cancelled() + try: + self.acquire_nowait() + except WouldBlock: + task = get_current_task() + event = Event() + token = task, event + self._waiters.append(token) + try: + await event.wait() + except BaseException: + if not event.is_set(): + self._waiters.remove(token) + elif self._owner_task == task: + self.release() + + raise + + assert self._owner_task == task + else: + try: + await cancel_shielded_checkpoint() + except BaseException: + self.release() + raise + + def acquire_nowait(self) -> None: + """ + Acquire the lock, without blocking. + + :raises ~WouldBlock: if the operation would block + + """ + task = get_current_task() + if self._owner_task == task: + raise RuntimeError("Attempted to acquire an already held Lock") + + if self._owner_task is not None: + raise WouldBlock + + self._owner_task = task + + def release(self) -> DeprecatedAwaitable: + """Release the lock.""" + if self._owner_task != get_current_task(): + raise RuntimeError("The current task is not holding this lock") + + if self._waiters: + self._owner_task, event = self._waiters.popleft() + event.set() + else: + del self._owner_task + + return DeprecatedAwaitable(self.release) + + def locked(self) -> bool: + """Return True if the lock is currently held.""" + return self._owner_task is not None + + def statistics(self) -> LockStatistics: + """ + Return statistics about the current state of this lock. + + .. versionadded:: 3.0 + """ + return LockStatistics(self.locked(), self._owner_task, len(self._waiters)) + + +class Condition: + _owner_task: Optional[TaskInfo] = None + + def __init__(self, lock: Optional[Lock] = 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: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> 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 ~WouldBlock: if the operation would block + + """ + self._lock.acquire_nowait() + self._owner_task = get_current_task() + + def release(self) -> DeprecatedAwaitable: + """Release the underlying lock.""" + self._lock.release() + return DeprecatedAwaitable(self.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() + 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() + + 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 __init__(self, initial_value: int, *, max_value: Optional[int] = None): + 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._value = initial_value + self._max_value = max_value + self._waiters: Deque[Event] = deque() + + async def __aenter__(self) -> "Semaphore": + await self.acquire() + return self + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.release() + + async def acquire(self) -> None: + """Decrement the semaphore value, blocking if necessary.""" + await checkpoint_if_cancelled() + try: + self.acquire_nowait() + except WouldBlock: + event = Event() + self._waiters.append(event) + try: + await event.wait() + except BaseException: + if not event.is_set(): + self._waiters.remove(event) + else: + self.release() + + raise + else: + try: + await cancel_shielded_checkpoint() + except BaseException: + self.release() + raise + + def acquire_nowait(self) -> None: + """ + Acquire the underlying lock, without blocking. + + :raises ~WouldBlock: if the operation would block + + """ + if self._value == 0: + raise WouldBlock + + self._value -= 1 + + def release(self) -> DeprecatedAwaitable: + """Increment the semaphore value.""" + if self._max_value is not None and self._value == self._max_value: + raise ValueError("semaphore released too many times") + + if self._waiters: + self._waiters.popleft().set() + else: + self._value += 1 + + return DeprecatedAwaitable(self.release) + + @property + def value(self) -> int: + """The current value of the semaphore.""" + return self._value + + @property + def max_value(self) -> Optional[int]: + """The maximum value of the semaphore.""" + return self._max_value + + def statistics(self) -> SemaphoreStatistics: + """ + Return statistics about the current state of this semaphore. + + .. versionadded:: 3.0 + """ + return SemaphoreStatistics(len(self._waiters)) + + +class CapacityLimiter: + def __new__(cls, total_tokens: float) -> "CapacityLimiter": + return get_asynclib().CapacityLimiter(total_tokens) + + async def __aenter__(self) -> None: + raise NotImplementedError + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + 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. + + """ + raise NotImplementedError + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + raise NotImplementedError + + async def set_total_tokens(self, value: float) -> None: + warn( + "CapacityLimiter.set_total_tokens has been deprecated. Set the value of the" + '"total_tokens" attribute directly.', + DeprecationWarning, + ) + self.total_tokens = value + + @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) -> DeprecatedAwaitable: + """ + 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) -> DeprecatedAwaitable: + """ + 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 + + +def create_lock() -> Lock: + """ + Create an asynchronous lock. + + :return: a lock object + + .. deprecated:: 3.0 + Use :class:`~Lock` directly. + + """ + warn("create_lock() is deprecated -- use Lock() directly", DeprecationWarning) + return Lock() + + +def create_condition(lock: Optional[Lock] = None) -> Condition: + """ + Create an asynchronous condition. + + :param lock: the lock to base the condition object on + :return: a condition object + + .. deprecated:: 3.0 + Use :class:`~Condition` directly. + + """ + warn( + "create_condition() is deprecated -- use Condition() directly", + DeprecationWarning, + ) + return Condition(lock=lock) + + +def create_event() -> Event: + """ + Create an asynchronous event object. + + :return: an event object + + .. deprecated:: 3.0 + Use :class:`~Event` directly. + + """ + warn("create_event() is deprecated -- use Event() directly", DeprecationWarning) + return get_asynclib().Event() + + +def create_semaphore(value: int, *, max_value: Optional[int] = None) -> Semaphore: + """ + Create an asynchronous semaphore. + + :param value: the semaphore's initial value + :param max_value: if set, makes this a "bounded" semaphore that raises :exc:`ValueError` if the + semaphore's value would exceed this number + :return: a semaphore object + + .. deprecated:: 3.0 + Use :class:`~Semaphore` directly. + + """ + warn( + "create_semaphore() is deprecated -- use Semaphore() directly", + DeprecationWarning, + ) + return Semaphore(value, max_value=max_value) + + +def create_capacity_limiter(total_tokens: float) -> CapacityLimiter: + """ + Create a capacity limiter. + + :param total_tokens: the total number of tokens available for borrowing (can be an integer or + :data:`math.inf`) + :return: a capacity limiter object + + .. deprecated:: 3.0 + Use :class:`~CapacityLimiter` directly. + + """ + warn( + "create_capacity_limiter() is deprecated -- use CapacityLimiter() directly", + DeprecationWarning, + ) + return get_asynclib().CapacityLimiter(total_tokens) + + +class ResourceGuard: + __slots__ = "action", "_guarded" + + def __init__(self, action: str): + self.action = action + self._guarded = False + + def __enter__(self) -> None: + if self._guarded: + raise BusyResourceError(self.action) + + self._guarded = True + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + self._guarded = False + return None diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_tasks.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_tasks.py new file mode 100644 index 00000000..f24764cf --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_tasks.py @@ -0,0 +1,178 @@ +import math +from types import TracebackType +from typing import Optional, Type +from warnings import warn + +from ..abc._tasks import TaskGroup, TaskStatus +from ._compat import ( + DeprecatedAsyncContextManager, + DeprecatedAwaitable, + DeprecatedAwaitableFloat, +) +from ._eventloop import get_asynclib + + +class _IgnoredTaskStatus(TaskStatus): + def started(self, value: object = None) -> None: + pass + + +TASK_STATUS_IGNORED = _IgnoredTaskStatus() + + +class CancelScope(DeprecatedAsyncContextManager["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_asynclib().CancelScope(shield=shield, deadline=deadline) + + def cancel(self) -> DeprecatedAwaitable: + """Cancel this scope immediately.""" + 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 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: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + raise NotImplementedError + + +def open_cancel_scope(*, shield: bool = False) -> CancelScope: + """ + Open a cancel scope. + + :param shield: ``True`` to shield the cancel scope from external cancellation + :return: a cancel scope + + .. deprecated:: 3.0 + Use :class:`~CancelScope` directly. + + """ + warn( + "open_cancel_scope() is deprecated -- use CancelScope() directly", + DeprecationWarning, + ) + return get_asynclib().CancelScope(shield=shield) + + +class FailAfterContextManager(DeprecatedAsyncContextManager[CancelScope]): + def __init__(self, cancel_scope: CancelScope): + self._cancel_scope = cancel_scope + + def __enter__(self) -> CancelScope: + return self._cancel_scope.__enter__() + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + retval = self._cancel_scope.__exit__(exc_type, exc_val, exc_tb) + if self._cancel_scope.cancel_called: + raise TimeoutError + + return retval + + +def fail_after(delay: Optional[float], shield: bool = False) -> FailAfterContextManager: + """ + 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.abc.CancelScope`\\] + + """ + deadline = ( + (get_asynclib().current_time() + delay) if delay is not None else math.inf + ) + cancel_scope = get_asynclib().CancelScope(deadline=deadline, shield=shield) + return FailAfterContextManager(cancel_scope) + + +def move_on_after(delay: Optional[float], 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_asynclib().current_time() + delay) if delay is not None else math.inf + ) + return get_asynclib().CancelScope(deadline=deadline, shield=shield) + + +def current_effective_deadline() -> DeprecatedAwaitableFloat: + """ + 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 (``float('inf')`` if there is no + deadline in effect) + :rtype: float + + """ + return DeprecatedAwaitableFloat( + get_asynclib().current_effective_deadline(), current_effective_deadline + ) + + +def create_task_group() -> "TaskGroup": + """ + Create a task group. + + :return: a task group + + """ + return get_asynclib().TaskGroup() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_testing.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_testing.py new file mode 100644 index 00000000..4998753a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_testing.py @@ -0,0 +1,80 @@ +from typing import Any, Awaitable, Generator, Optional, Union + +from ._compat import DeprecatedAwaitableList, _warn_deprecation +from ._eventloop import get_asynclib + + +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: Optional[int], + name: Optional[str], + coro: Union[Generator, Awaitable[Any]], + ): + func = get_current_task + self._name = f"{func.__module__}.{func.__qualname__}" + self.id: int = id + self.parent_id: Optional[int] = parent_id + self.name: Optional[str] = name + self.coro: Union[Generator, 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 __await__(self) -> Generator[None, None, "TaskInfo"]: + _warn_deprecation(self) + if False: + yield + + return self + + def _unwrap(self) -> "TaskInfo": + return self + + +def get_current_task() -> TaskInfo: + """ + Return the current task. + + :return: a representation of the current task + + """ + return get_asynclib().get_current_task() + + +def get_running_tasks() -> DeprecatedAwaitableList[TaskInfo]: + """ + Return a list of running tasks in the current event loop. + + :return: a list of task info objects + + """ + tasks = get_asynclib().get_running_tasks() + return DeprecatedAwaitableList(tasks, func=get_running_tasks) + + +async def wait_all_tasks_blocked() -> None: + """Wait until all other tasks are waiting for something.""" + await get_asynclib().wait_all_tasks_blocked() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_typedattr.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_typedattr.py new file mode 100644 index 00000000..424836a1 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/_core/_typedattr.py @@ -0,0 +1,81 @@ +import sys +from typing import Any, Callable, Dict, Mapping, TypeVar, Union, overload + +from ._exceptions import TypedAttributeLookupError + +if sys.version_info >= (3, 8): + from typing import final +else: + from typing_extensions import final + +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) -> Union[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: + return self.extra_attributes[attribute]() + except KeyError: + if default is undefined: + raise TypedAttributeLookupError("Attribute not found") from None + else: + return default diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/__init__.py new file mode 100644 index 00000000..72c44449 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/__init__.py @@ -0,0 +1,88 @@ +__all__ = ( + "AsyncResource", + "IPAddressType", + "IPSockAddrType", + "SocketAttribute", + "SocketStream", + "SocketListener", + "UDPSocket", + "UNIXSocketStream", + "UDPPacketType", + "ConnectedUDPSocket", + "UnreliableObjectReceiveStream", + "UnreliableObjectSendStream", + "UnreliableObjectStream", + "ObjectReceiveStream", + "ObjectSendStream", + "ObjectStream", + "ByteReceiveStream", + "ByteSendStream", + "ByteStream", + "AnyUnreliableByteReceiveStream", + "AnyUnreliableByteSendStream", + "AnyUnreliableByteStream", + "AnyByteReceiveStream", + "AnyByteSendStream", + "AnyByteStream", + "Listener", + "Process", + "Event", + "Condition", + "Lock", + "Semaphore", + "CapacityLimiter", + "CancelScope", + "TaskGroup", + "TaskStatus", + "TestRunner", + "BlockingPortal", +) + +from typing import Any + +from ._resources import AsyncResource +from ._sockets import ( + ConnectedUDPSocket, + IPAddressType, + IPSockAddrType, + SocketAttribute, + SocketListener, + SocketStream, + UDPPacketType, + UDPSocket, + UNIXSocketStream, +) +from ._streams import ( + AnyByteReceiveStream, + AnyByteSendStream, + AnyByteStream, + AnyUnreliableByteReceiveStream, + AnyUnreliableByteSendStream, + AnyUnreliableByteStream, + ByteReceiveStream, + ByteSendStream, + ByteStream, + Listener, + ObjectReceiveStream, + ObjectSendStream, + ObjectStream, + UnreliableObjectReceiveStream, + UnreliableObjectSendStream, + UnreliableObjectStream, +) +from ._subprocesses import Process +from ._tasks import TaskGroup, TaskStatus +from ._testing import TestRunner + +# Re-exported here, for backwards compatibility +# isort: off +from .._core._synchronization import CapacityLimiter, Condition, Event, Lock, Semaphore +from .._core._tasks import CancelScope +from ..from_thread import BlockingPortal + +# Re-export imports so they look like they live directly in this package +key: str +value: Any +for key, value in list(locals().items()): + if getattr(value, "__module__", "").startswith("anyio.abc."): + value.__module__ = __name__ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_resources.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_resources.py new file mode 100644 index 00000000..4f66c38e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_resources.py @@ -0,0 +1,29 @@ +from abc import ABCMeta, abstractmethod +from types import TracebackType +from typing import Optional, Type, 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. + """ + + async def __aenter__(self: T) -> T: + return self + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + await self.aclose() + + @abstractmethod + async def aclose(self) -> None: + """Close the resource.""" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_sockets.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_sockets.py new file mode 100644 index 00000000..f73e795e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_sockets.py @@ -0,0 +1,183 @@ +import socket +from abc import abstractmethod +from io import IOBase +from ipaddress import IPv4Address, IPv6Address +from socket import AddressFamily +from types import TracebackType +from typing import ( + Any, + AsyncContextManager, + Callable, + Collection, + Dict, + List, + Mapping, + Optional, + Tuple, + Type, + TypeVar, + Union, +) + +from .._core._typedattr import ( + TypedAttributeProvider, + TypedAttributeSet, + typed_attribute, +) +from ._streams import ByteStream, Listener, T_Stream, UnreliableObjectStream +from ._tasks import TaskGroup + +IPAddressType = Union[str, IPv4Address, IPv6Address] +IPSockAddrType = Tuple[str, int] +SockAddrType = Union[IPSockAddrType, str] +UDPPacketType = Tuple[bytes, IPSockAddrType] +T_Retval = TypeVar("T_Retval") + + +class _NullAsyncContextManager: + async def __aenter__(self) -> None: + pass + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + return None + + +class SocketAttribute(TypedAttributeSet): + #: the address family of the underlying socket + family: AddressFamily = typed_attribute() + #: the local socket address of the underlying socket + local_address: SockAddrType = typed_attribute() + #: for IP addresses, the local port the underlying socket is bound to + local_port: int = typed_attribute() + #: the underlying stdlib socket object + raw_socket: socket.socket = typed_attribute() + #: the remote address the underlying socket is connected to + remote_address: SockAddrType = typed_attribute() + #: for IP addresses, the remote port the underlying socket is connected to + 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: Optional[Tuple[str, int]] = 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`. + """ + + +class UNIXSocketStream(SocketStream): + @abstractmethod + async def send_fds( + self, message: bytes, fds: Collection[Union[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`. + """ + + @abstractmethod + async def accept(self) -> SocketStream: + """Accept an incoming connection.""" + + async def serve( + self, handler: Callable[[T_Stream], Any], task_group: Optional[TaskGroup] = None + ) -> None: + from .. import create_task_group + + context_manager: AsyncContextManager + if task_group is None: + task_group = context_manager = create_task_group() + else: + # Can be replaced with AsyncExitStack once on py3.7+ + context_manager = _NullAsyncContextManager() + + async with context_manager: + 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`. + """ + + 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`. + """ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_streams.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_streams.py new file mode 100644 index 00000000..4980ef4f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_streams.py @@ -0,0 +1,198 @@ +from abc import abstractmethod +from typing import Any, Callable, Generic, Optional, TypeVar, Union + +from .._core._exceptions import EndOfStream +from .._core._typedattr import TypedAttributeProvider +from ._resources import AsyncResource +from ._tasks import TaskGroup + +T_Item = TypeVar("T_Item") +T_Stream = TypeVar("T_Stream") + + +class UnreliableObjectReceiveStream( + Generic[T_Item], 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_Item]": + return self + + async def __anext__(self) -> T_Item: + try: + return await self.receive() + except EndOfStream: + raise StopAsyncIteration + + @abstractmethod + async def receive(self) -> T_Item: + """ + 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_Item], 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_Item) -> 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_Item]): + """ + 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_Item]): + """ + 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 + + @abstractmethod + async def receive(self, max_bytes: int = 65536) -> bytes: + """ + Receive at most ``max_bytes`` bytes from the peer. + + .. note:: Implementors 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 = Union[ + UnreliableObjectReceiveStream[bytes], ByteReceiveStream +] +#: Type alias for all unreliable bytes-oriented send streams. +AnyUnreliableByteSendStream = Union[UnreliableObjectSendStream[bytes], ByteSendStream] +#: Type alias for all unreliable bytes-oriented streams. +AnyUnreliableByteStream = Union[UnreliableObjectStream[bytes], ByteStream] +#: Type alias for all bytes-oriented receive streams. +AnyByteReceiveStream = Union[ObjectReceiveStream[bytes], ByteReceiveStream] +#: Type alias for all bytes-oriented send streams. +AnyByteSendStream = Union[ObjectSendStream[bytes], ByteSendStream] +#: Type alias for all bytes-oriented streams. +AnyByteStream = Union[ObjectStream[bytes], ByteStream] + + +class Listener(Generic[T_Stream], AsyncResource, TypedAttributeProvider): + """An interface for objects that let you accept incoming connections.""" + + @abstractmethod + async def serve( + self, handler: Callable[[T_Stream], Any], task_group: Optional[TaskGroup] = 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) + """ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_subprocesses.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_subprocesses.py new file mode 100644 index 00000000..1e633fb9 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_subprocesses.py @@ -0,0 +1,78 @@ +from abc import abstractmethod +from signal import Signals +from typing import Optional + +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) -> Optional[int]: + """ + The return code of the process. If the process has not yet terminated, this will be + ``None``. + """ + + @property + @abstractmethod + def stdin(self) -> Optional[ByteSendStream]: + """The stream for the standard input of the process.""" + + @property + @abstractmethod + def stdout(self) -> Optional[ByteReceiveStream]: + """The stream for the standard output of the process.""" + + @property + @abstractmethod + def stderr(self) -> Optional[ByteReceiveStream]: + """The stream for the standard error output of the process.""" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_tasks.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_tasks.py new file mode 100644 index 00000000..99928a1f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_tasks.py @@ -0,0 +1,104 @@ +import typing +from abc import ABCMeta, abstractmethod +from types import TracebackType +from typing import Any, Callable, Coroutine, Optional, Type, TypeVar +from warnings import warn + +if typing.TYPE_CHECKING: + from anyio._core._tasks import CancelScope + +T_Retval = TypeVar("T_Retval") + + +class TaskStatus(metaclass=ABCMeta): + @abstractmethod + def started(self, value: object = 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 + """ + + cancel_scope: "CancelScope" + + async def spawn( + self, + func: Callable[..., Coroutine[Any, Any, Any]], + *args: object, + 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 + + .. deprecated:: 3.0 + Use :meth:`start_soon` instead. If your code needs AnyIO 2 compatibility, you + can keep using this until AnyIO 4. + + """ + warn( + 'spawn() is deprecated -- use start_soon() (without the "await") instead', + DeprecationWarning, + ) + self.start_soon(func, *args, name=name) + + @abstractmethod + def start_soon( + self, + func: Callable[..., Coroutine[Any, Any, Any]], + *args: object, + 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[..., Coroutine[Any, Any, Any]], + *args: object, + name: object = None + ) -> object: + """ + Start a new task and wait until it signals for readiness. + + :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 + :return: the value passed to ``task_status.started()`` + :raises RuntimeError: if the task finishes without calling ``task_status.started()`` + + .. 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: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[bool]: + """Exit the task group context waiting for all tasks to finish.""" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_testing.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_testing.py new file mode 100644 index 00000000..4e3621df --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/abc/_testing.py @@ -0,0 +1,68 @@ +import types +from abc import ABCMeta, abstractmethod +from collections.abc import AsyncGenerator, Iterable +from typing import Any, Callable, Coroutine, Dict, Optional, Type, 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 + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[types.TracebackType], + ) -> Optional[bool]: + self.close() + return None + + @abstractmethod + def close(self) -> None: + """Close the event loop.""" + + @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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/from_thread.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/from_thread.py new file mode 100644 index 00000000..e4f871fd --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/from_thread.py @@ -0,0 +1,502 @@ +import threading +from asyncio import iscoroutine +from concurrent.futures import FIRST_COMPLETED, Future, ThreadPoolExecutor, wait +from contextlib import AbstractContextManager, contextmanager +from types import TracebackType +from typing import ( + Any, + AsyncContextManager, + Callable, + ContextManager, + Coroutine, + Dict, + Generator, + Iterable, + Optional, + Tuple, + Type, + TypeVar, + Union, + cast, + overload, +) +from warnings import warn + +from ._core import _eventloop +from ._core._eventloop import get_asynclib, get_cancelled_exc_class, threadlocals +from ._core._synchronization import Event +from ._core._tasks import CancelScope, create_task_group +from .abc._tasks import TaskStatus + +T_Retval = TypeVar("T_Retval") +T_co = TypeVar("T_co") + + +def run(func: Callable[..., Coroutine[Any, Any, T_Retval]], *args: object) -> T_Retval: + """ + Call a coroutine function from a worker thread. + + :param func: a coroutine function + :param args: positional arguments for the callable + :return: the return value of the coroutine function + + """ + try: + asynclib = threadlocals.current_async_module + except AttributeError: + raise RuntimeError("This function can only be run from an AnyIO worker thread") + + return asynclib.run_async_from_thread(func, *args) + + +def run_async_from_thread( + func: Callable[..., Coroutine[Any, Any, T_Retval]], *args: object +) -> T_Retval: + warn( + "run_async_from_thread() has been deprecated, use anyio.from_thread.run() instead", + DeprecationWarning, + ) + return run(func, *args) + + +def run_sync(func: Callable[..., T_Retval], *args: object) -> 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 + :return: the return value of the callable + + """ + try: + asynclib = threadlocals.current_async_module + except AttributeError: + raise RuntimeError("This function can only be run from an AnyIO worker thread") + + return asynclib.run_sync_from_thread(func, *args) + + +def run_sync_from_thread(func: Callable[..., T_Retval], *args: object) -> T_Retval: + warn( + "run_sync_from_thread() has been deprecated, use anyio.from_thread.run_sync() instead", + DeprecationWarning, + ) + return run_sync(func, *args) + + +class _BlockingAsyncContextManager(AbstractContextManager): + _enter_future: Future + _exit_future: Future + _exit_event: Event + _exit_exc_info: Tuple[ + Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType] + ] = (None, None, None) + + def __init__(self, async_cm: AsyncContextManager[T_co], portal: "BlockingPortal"): + self._async_cm = async_cm + self._portal = portal + + async def run_async_cm(self) -> Optional[bool]: + 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) + cm = self._enter_future.result() + return cast(T_co, cm) + + def __exit__( + self, + __exc_type: Optional[Type[BaseException]], + __exc_value: Optional[BaseException], + __traceback: Optional[TracebackType], + ) -> Optional[bool]: + 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_asynclib().BlockingPortal() + + def __init__(self) -> None: + self._event_loop_thread_id: Optional[int] = threading.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: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> Optional[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 == threading.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() + + async def _call_func( + self, func: Callable, args: tuple, kwargs: Dict[str, Any], future: Future + ) -> None: + def callback(f: Future) -> None: + if f.cancelled() and self._event_loop_thread_id not in ( + None, + threading.get_ident(), + ): + self.call(scope.cancel) + + try: + retval = func(*args, **kwargs) + if iscoroutine(retval): + with CancelScope() as scope: + if future.cancelled(): + scope.cancel() + else: + future.add_done_callback(callback) + + retval = await retval + except self._cancelled_exc_class: + future.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, + args: tuple, + kwargs: Dict[str, Any], + name: object, + future: Future, + ) -> None: + """ + Spawn a new task using the given callable. + + Implementors 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[..., Coroutine[Any, Any, T_Retval]], *args: object + ) -> T_Retval: + ... + + @overload + def call(self, func: Callable[..., T_Retval], *args: object) -> T_Retval: + ... + + def call( + self, + func: Callable[..., Union[Coroutine[Any, Any, T_Retval], T_Retval]], + *args: object + ) -> 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 spawn_task( + self, + func: Callable[..., Coroutine[Any, Any, T_Retval]], + *args: object, + name: object = None + ) -> "Future[T_Retval]": + ... + + @overload + def spawn_task( + self, func: Callable[..., T_Retval], *args: object, name: object = None + ) -> "Future[T_Retval]": + ... + + def spawn_task( + self, + func: Callable[..., Union[Coroutine[Any, Any, T_Retval], T_Retval]], + *args: object, + name: object = None + ) -> "Future[T_Retval]": + """ + Start a task in the portal's task group. + + :param func: the target coroutine 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 + + .. versionadded:: 2.1 + .. deprecated:: 3.0 + Use :meth:`start_task_soon` instead. If your code needs AnyIO 2 compatibility, you + can keep using this until AnyIO 4. + + """ + warn( + "spawn_task() is deprecated -- use start_task_soon() instead", + DeprecationWarning, + ) + return self.start_task_soon(func, *args, name=name) # type: ignore[arg-type] + + @overload + def start_task_soon( + self, + func: Callable[..., Coroutine[Any, Any, T_Retval]], + *args: object, + name: object = None + ) -> "Future[T_Retval]": + ... + + @overload + def start_task_soon( + self, func: Callable[..., T_Retval], *args: object, name: object = None + ) -> "Future[T_Retval]": + ... + + def start_task_soon( + self, + func: Callable[..., Union[Coroutine[Any, Any, T_Retval], T_Retval]], + *args: object, + 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 coroutine 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 + + .. versionadded:: 3.0 + + """ + self._check_running() + f: Future = Future() + self._spawn_task_from_thread(func, args, {}, name, f) + return f + + def start_task( + self, + func: Callable[..., Coroutine[Any, Any, Any]], + *args: object, + name: object = None + ) -> Tuple["Future[Any]", 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:`TaskGroup.start`. + + :param func: the target coroutine 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 + + .. versionadded:: 3.0 + + """ + + def task_done(future: Future) -> 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: AsyncContextManager[T_co] + ) -> ContextManager[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) + + +def create_blocking_portal() -> BlockingPortal: + """ + Create a portal for running functions in the event loop thread from external threads. + + Use this function in asynchronous code when you need to allow external threads access to the + event loop where your asynchronous code is currently running. + + .. deprecated:: 3.0 + Use :class:`.BlockingPortal` directly. + + """ + warn( + "create_blocking_portal() has been deprecated -- use anyio.from_thread.BlockingPortal() " + "directly", + DeprecationWarning, + ) + return BlockingPortal() + + +@contextmanager +def start_blocking_portal( + backend: str = "asyncio", backend_options: Optional[Dict[str, Any]] = 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 + :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 future.set_running_or_notify_cancel(): + future.set_result(portal_) + await portal_.sleep_until_stopped() + + future: Future[BlockingPortal] = Future() + with ThreadPoolExecutor(1) as executor: + run_future = executor.submit( + _eventloop.run, + run_portal, # type: ignore[arg-type] + backend=backend, + backend_options=backend_options, + ) + try: + wait( + cast(Iterable[Future], [run_future, future]), + return_when=FIRST_COMPLETED, + ) + except BaseException: + future.cancel() + run_future.cancel() + raise + + if future.done(): + portal = future.result() + try: + yield portal + except BaseException: + portal.call(portal.stop, True) + raise + + portal.call(portal.stop, False) + + run_future.result() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/lowlevel.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/lowlevel.py new file mode 100644 index 00000000..c1da8fa5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/lowlevel.py @@ -0,0 +1,170 @@ +import enum +import sys +from dataclasses import dataclass +from typing import Any, Dict, Generic, Set, TypeVar, Union, overload +from weakref import WeakKeyDictionary + +from ._core._eventloop import get_asynclib + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal + +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_asynclib().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_asynclib().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_asynclib().cancel_shielded_checkpoint() + + +def current_token() -> object: + """Return a backend specific token object that can be used to get back to the event loop.""" + return get_asynclib().current_token() + + +_run_vars = WeakKeyDictionary() # type: WeakKeyDictionary[Any, Dict[str, Any]] +_token_wrappers: Dict[Any, "_TokenWrapper"] = {} + + +@dataclass(frozen=True) +class _TokenWrapper: + __slots__ = "_token", "__weakref__" + _token: object + + +class _NoValueSet(enum.Enum): + NO_VALUE_SET = enum.auto() + + +class RunvarToken(Generic[T]): + __slots__ = "_var", "_value", "_redeemed" + + def __init__( + self, var: "RunVar[T]", value: Union[T, Literal[_NoValueSet.NO_VALUE_SET]] + ): + self._var = var + self._value: Union[T, Literal[_NoValueSet.NO_VALUE_SET]] = value + self._redeemed = False + + +class RunVar(Generic[T]): + """Like a :class:`~contextvars.ContextVar`, expect scoped to the running event loop.""" + + __slots__ = "_name", "_default" + + NO_VALUE_SET: Literal[_NoValueSet.NO_VALUE_SET] = _NoValueSet.NO_VALUE_SET + + _token_wrappers: Set[_TokenWrapper] = set() + + def __init__( + self, + name: str, + default: Union[T, Literal[_NoValueSet.NO_VALUE_SET]] = NO_VALUE_SET, + ): + self._name = name + self._default = default + + @property + def _current_vars(self) -> Dict[str, T]: + token = current_token() + while True: + try: + return _run_vars[token] + except TypeError: + # Happens when token isn't weak referable (TrioToken). + # This workaround does mean that some memory will leak on Trio until the problem + # is fixed on their end. + token = _TokenWrapper(token) + self._token_wrappers.add(token) + except KeyError: + run_vars = _run_vars[token] = {} + return run_vars + + @overload + def get(self, default: D) -> Union[T, D]: + ... + + @overload + def get(self) -> T: + ... + + def get( + self, default: Union[D, Literal[_NoValueSet.NO_VALUE_SET]] = NO_VALUE_SET + ) -> Union[T, D]: + try: + return self._current_vars[self._name] + 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._name, RunVar.NO_VALUE_SET)) + current_vars[self._name] = 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._name] + except KeyError: + pass + else: + self._current_vars[self._name] = token._value + + token._redeemed = True + + def __repr__(self) -> str: + return f"" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/pytest_plugin.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/pytest_plugin.py new file mode 100644 index 00000000..432eee3b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/pytest_plugin.py @@ -0,0 +1,144 @@ +from contextlib import contextmanager +from inspect import isasyncgenfunction, iscoroutinefunction +from typing import TYPE_CHECKING, Any, Dict, Generator, Optional, Tuple, cast + +import pytest +import sniffio +from _pytest.fixtures import FixtureRequest + +from ._core._eventloop import get_all_backends, get_asynclib +from .abc import TestRunner + +if TYPE_CHECKING: + from _pytest.config import Config + +_current_runner: Optional[TestRunner] = None + + +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] +) -> Generator[TestRunner, object, None]: + global _current_runner + if _current_runner: + yield _current_runner + return + + asynclib = get_asynclib(backend_name) + token = None + if sniffio.current_async_library_cvar.get(None) is None: + # Since we're in control of the event loop, we can cache the name of the async library + token = sniffio.current_async_library_cvar.set(backend_name) + + try: + backend_options = backend_options or {} + with asynclib.TestRunner(**backend_options) as runner: + _current_runner = runner + yield runner + finally: + _current_runner = None + if token: + sniffio.current_async_library_cvar.reset(token) + + +def pytest_configure(config: "Config") -> None: + config.addinivalue_line( + "markers", + "anyio: mark the (coroutine function) test to be run " + "asynchronously via anyio.", + ) + + +def pytest_fixture_setup(fixturedef: Any, request: FixtureRequest) -> None: + def wrapper(*args, anyio_backend, **kwargs): # type: ignore[no-untyped-def] + backend_name, backend_options = extract_backend_and_options(anyio_backend) + if has_backend_arg: + kwargs["anyio_backend"] = anyio_backend + + with get_runner(backend_name, backend_options) as runner: + if isasyncgenfunction(func): + yield from runner.run_asyncgen_fixture(func, kwargs) + else: + yield runner.run_fixture(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: + has_backend_arg = "anyio_backend" in fixturedef.argnames + fixturedef.func = wrapper + if not has_backend_arg: + fixturedef.argnames += ("anyio_backend",) + + +@pytest.hookimpl(tryfirst=True) +def pytest_pycollect_makeitem(collector: Any, name: Any, obj: Any) -> None: + if collector.istestfunction(obj, name): + inner_func = obj.hypothesis.inner_test if hasattr(obj, "hypothesis") else obj + if iscoroutinefunction(inner_func): + marker = collector.get_closest_marker("anyio") + own_markers = getattr(obj, "pytestmark", ()) + if 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) -> Optional[bool]: + 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: + runner.run_test(pyfuncitem.obj, testargs) + + return True + + return None + + +@pytest.fixture(params=get_all_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] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/buffered.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/buffered.py new file mode 100644 index 00000000..1503b3e4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/buffered.py @@ -0,0 +1,116 @@ +from dataclasses import dataclass, field +from typing import Any, Callable, Mapping + +from .. import ClosedResourceError, DelimiterNotFound, EndOfStream, IncompleteRead +from ..abc import AnyByteReceiveStream, ByteReceiveStream + + +@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 + + 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) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/file.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/file.py new file mode 100644 index 00000000..938d1daa --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/file.py @@ -0,0 +1,145 @@ +from io import SEEK_SET, UnsupportedOperation +from os import PathLike +from pathlib import Path +from typing import Any, BinaryIO, Callable, Dict, Mapping, Union, 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: Union[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: Union[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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/memory.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/memory.py new file mode 100644 index 00000000..d8a958c7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/memory.py @@ -0,0 +1,275 @@ +from collections import OrderedDict, deque +from dataclasses import dataclass, field +from types import TracebackType +from typing import Deque, Generic, List, NamedTuple, Optional, Type, TypeVar + +from .. import ( + BrokenResourceError, + ClosedResourceError, + EndOfStream, + WouldBlock, + get_cancelled_exc_class, +) +from .._core._compat import DeprecatedAwaitable +from ..abc import Event, ObjectReceiveStream, ObjectSendStream +from ..lowlevel import checkpoint + +T_Item = TypeVar("T_Item") + + +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 + tasks_waiting_send: int #: number of tasks blocked on :meth:`MemoryObjectSendStream.send` + #: number of tasks blocked on :meth:`MemoryObjectReceiveStream.receive` + tasks_waiting_receive: int + + +@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, List[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_Item], ObjectReceiveStream[T_Item]): + _state: MemoryObjectStreamState[T_Item] + _closed: bool = field(init=False, default=False) + + def __post_init__(self) -> None: + self._state.open_receive_channels += 1 + + def receive_nowait(self) -> T_Item: + """ + 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_Item: + await checkpoint() + try: + return self.receive_nowait() + except WouldBlock: + # Add ourselves in the queue + receive_event = Event() + container: List[T_Item] = [] + self._state.waiting_receivers[receive_event] = container + + try: + await receive_event.wait() + except get_cancelled_exc_class(): + # Ignore the immediate cancellation if we already received an item, so as not to + # lose it + if not container: + raise + finally: + self._state.waiting_receivers.pop(receive_event, None) + + if container: + return container[0] + else: + raise EndOfStream + + def clone(self) -> "MemoryObjectReceiveStream[T_Item]": + """ + 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_Item]": + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.close() + + +@dataclass(eq=False) +class MemoryObjectSendStream(Generic[T_Item], ObjectSendStream[T_Item]): + _state: MemoryObjectStreamState[T_Item] + _closed: bool = field(init=False, default=False) + + def __post_init__(self) -> None: + self._state.open_send_channels += 1 + + def send_nowait(self, item: T_Item) -> DeprecatedAwaitable: + """ + 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 + + if self._state.waiting_receivers: + receive_event, container = self._state.waiting_receivers.popitem(last=False) + container.append(item) + receive_event.set() + elif len(self._state.buffer) < self._state.max_buffer_size: + self._state.buffer.append(item) + else: + raise WouldBlock + + return DeprecatedAwaitable(self.send_nowait) + + async def send(self, item: T_Item) -> None: + 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) # type: ignore[arg-type] + raise + + if self._state.waiting_senders.pop(send_event, None): # type: ignore[arg-type] + raise BrokenResourceError + + def clone(self) -> "MemoryObjectSendStream[T_Item]": + """ + 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_Item]": + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.close() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/stapled.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/stapled.py new file mode 100644 index 00000000..a71ffb0d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/stapled.py @@ -0,0 +1,138 @@ +from dataclasses import dataclass +from typing import Any, Callable, Generic, List, Mapping, Optional, Sequence, 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: Optional[TaskGroup] = 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/text.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/text.py new file mode 100644 index 00000000..ccb683c7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/text.py @@ -0,0 +1,141 @@ +import codecs +from dataclasses import InitVar, dataclass, field +from typing import Any, Callable, Mapping, Tuple + +from ..abc import ( + AnyByteReceiveStream, + AnyByteSendStream, + AnyByteStream, + ObjectReceiveStream, + ObjectSendStream, + ObjectStream, +) + + +@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, + } diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/tls.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/tls.py new file mode 100644 index 00000000..c8e19e2a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/streams/tls.py @@ -0,0 +1,317 @@ +import logging +import re +import ssl +from dataclasses import dataclass +from functools import wraps +from typing import Any, Callable, Dict, List, Mapping, Optional, Tuple, TypeVar, Union + +from .. import ( + BrokenResourceError, + EndOfStream, + aclose_forcefully, + get_cancelled_exc_class, +) +from .._core._typedattr import TypedAttributeSet, typed_attribute +from ..abc import AnyByteStream, ByteStream, Listener, TaskGroup + +T_Retval = TypeVar("T_Retval") +_PCTRTT = Tuple[Tuple[str, str], ...] +_PCTRTTT = Tuple[_PCTRTT, ...] + + +class TLSAttribute(TypedAttributeSet): + """Contains Transport Layer Security related attributes.""" + + #: the selected ALPN protocol + alpn_protocol: Optional[str] = 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: Optional[ + Dict[str, Union[str, _PCTRTTT, _PCTRTT]] + ] = typed_attribute() + #: the peer certificate in binary form + peer_certificate_binary: Optional[bytes] = typed_attribute() + #: ``True`` if this is the server side of the connection + server_side: bool = typed_attribute() + #: ciphers shared between both ends of the TLS connection + shared_ciphers: List[Tuple[str, str, int]] = 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: Optional[bool] = None, + hostname: Optional[str] = None, + ssl_context: Optional[ssl.SSLContext] = 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 # type: ignore[attr-defined] + + bio_in = ssl.MemoryBIO() + bio_out = ssl.MemoryBIO() + ssl_object = ssl_context.wrap_bio( + bio_in, bio_out, server_side=server_side, server_hostname=hostname + ) + 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[..., T_Retval], *args: object + ) -> 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 "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(), + 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: + f""" + 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 ``{__name__}`` + 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()): + logging.getLogger(__name__).exception("Error during TLS handshake") + + # 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: Optional[TaskGroup] = 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, + } diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_process.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_process.py new file mode 100644 index 00000000..39a31730 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_process.py @@ -0,0 +1,247 @@ +import os +import pickle +import subprocess +import sys +from collections import deque +from importlib.util import module_from_spec, spec_from_file_location +from typing import Callable, Deque, List, Optional, Set, Tuple, TypeVar, cast + +from ._core._eventloop import current_time, get_asynclib, 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 + +WORKER_MAX_IDLE_TIME = 300 # 5 minutes + +T_Retval = TypeVar("T_Retval") +_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( + func: Callable[..., T_Retval], + *args: object, + cancellable: bool = False, + limiter: Optional[CapacityLimiter] = 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_asynclib().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, idle_since = idle_workers.popleft() + process.kill() + workers.remove(process) + killed_processes.append(process) + + with CancelScope(shield=True): + for process in killed_processes: + await 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: Optional[str] + sys.path, main_module_path = args + del sys.modules["__main__"] + if 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_thread.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_thread.py new file mode 100644 index 00000000..a2fd42f4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/anyio/to_thread.py @@ -0,0 +1,65 @@ +from typing import Callable, Optional, TypeVar +from warnings import warn + +from ._core._eventloop import get_asynclib +from .abc import CapacityLimiter + +T_Retval = TypeVar("T_Retval") + + +async def run_sync( + func: Callable[..., T_Retval], + *args: object, + cancellable: bool = False, + limiter: Optional[CapacityLimiter] = 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 cancellable: ``True`` to allow cancellation of the operation + :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. + + """ + return await get_asynclib().run_sync_in_worker_thread( + func, *args, cancellable=cancellable, limiter=limiter + ) + + +async def run_sync_in_worker_thread( + func: Callable[..., T_Retval], + *args: object, + cancellable: bool = False, + limiter: Optional[CapacityLimiter] = None +) -> T_Retval: + warn( + "run_sync_in_worker_thread() has been deprecated, use anyio.to_thread.run_sync() instead", + DeprecationWarning, + ) + return await run_sync(func, *args, cancellable=cancellable, 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_asynclib().current_default_thread_limiter() + + +def current_default_worker_thread_limiter() -> CapacityLimiter: + warn( + "current_default_worker_thread_limiter() has been deprecated, " + "use anyio.to_thread.current_default_thread_limiter() instead", + DeprecationWarning, + ) + return current_default_thread_limiter() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/LICENSE.rst b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/LICENSE.rst new file mode 100644 index 00000000..d12a8491 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/LICENSE.rst @@ -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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/METADATA new file mode 100644 index 00000000..8e5dc1e0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/METADATA @@ -0,0 +1,111 @@ +Metadata-Version: 2.1 +Name: click +Version: 8.1.3 +Summary: Composable command line interface toolkit +Home-page: https://palletsprojects.com/p/click/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/click/ +Project-URL: Issue Tracker, https://github.com/pallets/click/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: colorama ; platform_system == "Windows" +Requires-Dist: importlib-metadata ; python_version < "3.8" + +\$ 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 + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U click + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: 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() + +.. code-block:: text + + $ 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 + + +Links +----- + +- Documentation: https://click.palletsprojects.com/ +- Changes: https://click.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/click/ +- Source Code: https://github.com/pallets/click +- Issue Tracker: https://github.com/pallets/click/issues +- Website: https://palletsprojects.com/p/click +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/RECORD new file mode 100644 index 00000000..d5b2ceb8 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/RECORD @@ -0,0 +1,39 @@ +click-8.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.1.3.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click-8.1.3.dist-info/METADATA,sha256=tFJIX5lOjx7c5LjZbdTPFVDJSgyv9F74XY0XCPp_gnc,3247 +click-8.1.3.dist-info/RECORD,, +click-8.1.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +click-8.1.3.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 +click/__init__.py,sha256=rQBLutqg-z6m8nOzivIfigDn_emijB_dKv9BZ2FNi5s,3138 +click/__pycache__/__init__.cpython-37.pyc,, +click/__pycache__/_compat.cpython-37.pyc,, +click/__pycache__/_termui_impl.cpython-37.pyc,, +click/__pycache__/_textwrap.cpython-37.pyc,, +click/__pycache__/_winconsole.cpython-37.pyc,, +click/__pycache__/core.cpython-37.pyc,, +click/__pycache__/decorators.cpython-37.pyc,, +click/__pycache__/exceptions.cpython-37.pyc,, +click/__pycache__/formatting.cpython-37.pyc,, +click/__pycache__/globals.cpython-37.pyc,, +click/__pycache__/parser.cpython-37.pyc,, +click/__pycache__/shell_completion.cpython-37.pyc,, +click/__pycache__/termui.cpython-37.pyc,, +click/__pycache__/testing.cpython-37.pyc,, +click/__pycache__/types.cpython-37.pyc,, +click/__pycache__/utils.cpython-37.pyc,, +click/_compat.py,sha256=JIHLYs7Jzz4KT9t-ds4o4jBzLjnwCiJQKqur-5iwCKI,18810 +click/_termui_impl.py,sha256=qK6Cfy4mRFxvxE8dya8RBhLpSC8HjF-lvBc6aNrPdwg,23451 +click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 +click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 +click/core.py,sha256=mz87bYEKzIoNYEa56BFAiOJnvt1Y0L-i7wD4_ZecieE,112782 +click/decorators.py,sha256=yo3zvzgUm5q7h5CXjyV6q3h_PJAiUaem178zXwdWUFI,16350 +click/exceptions.py,sha256=7gDaLGuFZBeCNwY9ERMsF2-Z3R9Fvq09Zc6IZSKjseo,9167 +click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 +click/globals.py,sha256=TP-qM88STzc7f127h35TD_v920FgfOD2EwzqA0oE8XU,1961 +click/parser.py,sha256=cAEt1uQR8gq3-S9ysqbVU-fdAZNvilxw4ReJ_T1OQMk,19044 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=qOp_BeC9esEOSZKyu5G7RIxEUaLsXUX-mTb7hB1r4QY,18018 +click/termui.py,sha256=ACBQVOvFCTSqtD5VREeCAdRtlHd-Imla-Lte4wSfMjA,28355 +click/testing.py,sha256=ptpMYgRY7dVfE3UDgkgwayu9ePw98sQI3D7zZXiCpj4,16063 +click/types.py,sha256=rEb1aZSQKq3ciCMmjpG2Uva9vk498XRL7ThrcK2GRss,35805 +click/utils.py,sha256=33D6E7poH_nrKB-xr-UyDEXnxOcCiQqxuRLtrqeVv6o,18682 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/top_level.txt new file mode 100644 index 00000000..dca9a909 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click-8.1.3.dist-info/top_level.txt @@ -0,0 +1 @@ +click diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/__init__.py new file mode 100644 index 00000000..e3ef423b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/__init__.py @@ -0,0 +1,73 @@ +""" +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 .core import Argument as Argument +from .core import BaseCommand as BaseCommand +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 MultiCommand as MultiCommand +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 .parser import OptionParser as OptionParser +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 + +__version__ = "8.1.3" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_compat.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_compat.py new file mode 100644 index 00000000..766d286b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_compat.py @@ -0,0 +1,626 @@ +import codecs +import io +import os +import re +import sys +import typing as t +from weakref import WeakKeyDictionary + +CYGWIN = sys.platform.startswith("cygwin") +MSYS2 = sys.platform.startswith("win") and ("GCC" in sys.version) +# Determine local App Engine environment, per Google's own suggestion +APP_ENGINE = "APPENGINE_RUNTIME" in os.environ and "Development/" in os.environ.get( + "SERVER_SOFTWARE", "" +) +WIN = sys.platform.startswith("win") and not APP_ENGINE and not MSYS2 +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None +_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") + + +def get_filesystem_encoding() -> str: + return sys.getfilesystemencoding() or sys.getdefaultencoding() + + +def _make_text_stream( + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> 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) -> 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: t.Optional[str], + errors: t.Optional[str], + 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("") # type: ignore + 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, 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, 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.Optional[t.BinaryIO]: + # 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.Optional[t.BinaryIO]: + # 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: t.Optional[str]) -> 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: t.Optional[str], errors: t.Optional[str] +) -> 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, + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO, bool], bool], + find_binary: t.Callable[[t.IO], t.Optional[t.BinaryIO]], + 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, + encoding: t.Optional[str], + errors: t.Optional[str], + 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, + encoding: t.Optional[str], + errors: t.Optional[str], + 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: t.Optional[str] = None, errors: t.Optional[str] = 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: t.Optional[str] = None, errors: t.Optional[str] = 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: t.Optional[str] = None, errors: t.Optional[str] = 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: t.Union[str, os.PathLike, int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO: + """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, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO, bool]: + binary = "b" in mode + + # 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: t.Optional[int] = 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, af), True + + +class _AtomicFile: + def __init__(self, f: t.IO, 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, exc_value, tb): # type: ignore + 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) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.Optional[t.IO] = None, color: t.Optional[bool] = 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: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi( + stream: t.TextIO, color: t.Optional[bool] = 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): + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or get_filesystem_encoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.TextIO], wrapper_func: t.Callable[[], t.TextIO] +) -> t.Callable[[], t.TextIO]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.TextIO: + stream = src_func() + 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: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_termui_impl.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_termui_impl.py new file mode 100644 index 00000000..4b979bcc --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_termui_impl.py @@ -0,0 +1,717 @@ +""" +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. +""" +import contextlib +import math +import os +import sys +import time +import typing as t +from gettext import gettext as _ + +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: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = 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.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label = label or "" + if file is None: + file = _default_text_stdout() + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width = width + self.autowidth = 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(t.Iterable[V], range(length)) + self.iter = iter(iterable) + self.length = length + self.pos = 0 + self.avg: t.List[float] = [] + self.start = self.last_eta = time.time() + self.eta_known = False + self.finished = False + self.max_width: t.Optional[int] = None + self.entered = False + self.current_item: t.Optional[V] = None + self.is_hidden = not isatty(self.file) + self._last_line: t.Optional[str] = None + + def __enter__(self) -> "ProgressBar": + self.entered = True + self.render_progress() + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.render_finish() + + def __iter__(self) -> t.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.is_hidden: + 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: + import shutil + + if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + 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: + 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: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) # type: ignore + 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: t.Optional[V] = 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) -> t.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 self.is_hidden: + 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: t.Iterable[str], color: t.Optional[bool] = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + pager_cmd = (os.environ.get("PAGER", None) or "").strip() + if pager_cmd: + if WIN: + return _tempfilepager(generator, pager_cmd, color) + return _pipepager(generator, pager_cmd, color) + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if WIN or sys.platform.startswith("os2"): + return _tempfilepager(generator, "more <", color) + if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0: + return _pipepager(generator, "less", color) + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if hasattr(os, "system") and os.system(f'more "{filename}"') == 0: + return _pipepager(generator, "more", color) + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + """ + import subprocess + + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit("/", 1)[-1].split() + if color is None and cmd_detail[0] == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env) + stdin = t.cast(t.BinaryIO, c.stdin) + encoding = get_best_encoding(stdin) + try: + for text in generator: + if not color: + text = strip_ansi(text) + + stdin.write(text.encode(encoding, "replace")) + except (OSError, KeyboardInterrupt): + pass + else: + stdin.close() + + # 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 + + +def _tempfilepager( + generator: t.Iterable[str], cmd: str, color: t.Optional[bool] +) -> None: + """Page through text by invoking a program on a temporary file.""" + 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: + os.system(f'{cmd} "{filename}"') + finally: + os.close(fd) + os.unlink(filename) + + +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> 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: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = 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" + for editor in "sensible-editor", "vim", "nano": + if os.system(f"which {editor} >/dev/null 2>&1") == 0: + return editor + return "vi" + + def edit_file(self, filename: str) -> None: + import subprocess + + editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + try: + c = subprocess.Popen(f'{editor} "{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 + + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: + import tempfile + + if not text: + data = 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_file(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") # type: ignore + 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.replace('"', "")) + args = f'explorer /select,"{url}"' + else: + url = url.replace('"', "") + wait_str = "/WAIT" if wait else "" + args = f'start {wait_str} "" "{url}"' + return os.system(args) + elif CYGWIN: + if locate: + url = os.path.dirname(_unquote_file(url).replace('"', "")) + args = f'cygstart "{url}"' + else: + url = url.replace('"', "") + wait_str = "-w" if wait else "" + args = f'cygstart {wait_str} "{url}"' + return os.system(args) + + 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) -> t.Optional[BaseException]: + 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 WIN: + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> t.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`. + func: t.Callable[[], str] + + if echo: + func = msvcrt.getwche # type: ignore + else: + func = msvcrt.getwch # type: ignore + + 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 tty + import termios + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_textwrap.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_textwrap.py new file mode 100644 index 00000000..b47dcbd4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_textwrap.py @@ -0,0 +1,49 @@ +import textwrap +import typing as t +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + def _handle_long_word( + self, + reversed_chunks: t.List[str], + cur_line: t.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) -> t.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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_winconsole.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_winconsole.py new file mode 100644 index 00000000..6b20df31 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/_winconsole.py @@ -0,0 +1,279 @@ +# 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. +import io +import sys +import time +import typing as t +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 + +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_ = [ + ("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, writable=False): + buf = Py_buffer() + flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + + try: + buffer_type = c_char * buf.len + return buffer_type.from_address(buf.buf) + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + def __init__(self, handle): + self.handle = handle + + def isatty(self): + super().isatty() + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + def readable(self): + return True + + def readinto(self, b): + 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): + return True + + @staticmethod + def _get_error_message(errno): + 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): + 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: t.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): + 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: t.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: t.Optional[str], errors: t.Optional[str] +) -> t.Optional[t.TextIO]: + if ( + get_buffer is not None + and encoding in {"utf-16-le", None} + and errors in {"strict", None} + and _is_console(f) + ): + func = _stream_factories.get(f.fileno()) + if func is not None: + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/core.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/core.py new file mode 100644 index 00000000..5abfb0f3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/core.py @@ -0,0 +1,2998 @@ +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from contextlib import contextmanager +from contextlib import ExitStack +from functools import partial +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat + +from . import types +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +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 _flag_needs_value +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: + import typing_extensions as te + 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 +) -> t.Iterator[t.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(MultiCommand, 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_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = ( + "It is not possible to add multi commands as children to" + " another multi command that is in chain mode." + ) + else: + hint = ( + "Found a multi command as subcommand to a multi command" + " that is in chain mode. This is not supported." + ) + raise RuntimeError( + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." + ) + + +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size))) + + +@contextmanager +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.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: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: + """Given a sequence of parameters in the order as should be considered + for processing and an iterable of parameters that exist, this returns + a list in the correct order as they should be processed. + """ + + def sort_key(item: "Parameter") -> t.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.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: t.Type["HelpFormatter"] = HelpFormatter + + def __init__( + self, + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.Dict[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = 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: t.Dict[str, t.Any] = {} + #: the leftover arguments. + self.args: t.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: t.List[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: t.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: t.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: t.Optional[t.Dict[str, t.Any]] = 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: t.Optional[str] = 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: t.Optional[int] = 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: t.Optional[int] = 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: t.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.Optional[ + t.Callable[[str], str] + ] = 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: t.Optional[str] = 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: t.Optional[bool] = 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: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + def to_info_dict(self) -> t.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, exc_value, tb): # type: ignore + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup: bool = True) -> t.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) -> t.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: t.ContextManager[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._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + @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: t.Type[V]) -> t.Optional[V]: + """Finds the closest object of a given type.""" + node: t.Optional["Context"] = 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: t.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: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """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) + + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.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) -> "te.NoReturn": + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> "te.NoReturn": + """Exits the application with a given exit code.""" + 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) + + def invoke( + __self, # noqa: B902 + __callback: t.Union["Command", t.Callable[..., t.Any]], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: + """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. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + 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 = other_cmd.callback + + ctx = __self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): + with ctx: + return __callback(*args, **kwargs) + + def forward( + __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 + ) -> 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) -> t.Optional[ParameterSource]: + """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 BaseCommand: + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :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. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.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: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + ) -> 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: t.Dict[str, t.Any] = context_settings + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get usage") + + def get_help(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get help") + + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = 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 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 # type: ignore + ) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError("Base commands do not know how to parse arguments.") + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError("Base commands are not invokable by default") + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :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: t.List["CompletionItem"] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) 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: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": + ... + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: + ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = 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): + echo(file=sys.stderr) + raise Abort() from None + 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: t.Dict[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = 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``. + """ + if complete_var is None: + complete_var = f"_{prog_name}_COMPLETE".replace("-", "_").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 Command(BaseCommand): + """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: issues a message indicating that + the command is deprecated. + + .. 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. + """ + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, 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: t.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.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + 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, + ) + return info_dict + + 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) -> t.List["Parameter"]: + rv = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + rv = [*rv, help_option] + + return rv + + 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) -> t.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) -> t.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) -> t.Optional["Option"]: + """Returns the help option object.""" + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + def show_help(ctx: Context, param: "Parameter", value: str) -> None: + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + return Option( + help_options, + is_flag=True, + is_eager=True, + expose_value=False, + callback=show_help, + help=_("Show this message and exit."), + ) + + 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: + text = _("(Deprecated) {text}").format(text=text) + + 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.""" + text = self.help if self.help is not None else "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + text = inspect.cleandoc(text).partition("\f")[0] + 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 parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + 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)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + 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) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options 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: t.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) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. + """ + + allow_extra_args = True + allow_interspersed_args = False + + def __init__( + self, + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + 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( + "Multi commands in chain mode cannot have" + " optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> t.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 collect_usage_pieces(self, ctx: Context) -> t.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 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, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) # type: ignore + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv + + return decorator + + 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: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + 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: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.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, 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 get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError + + def list_commands(self, ctx: Context) -> t.List[str]: + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + def shell_complete(self, ctx: Context, incomplete: str) -> t.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 Group(MultiCommand): + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. + + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commmands`` argument can be a list of command objects. + """ + + #: 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: t.Optional[t.Type[Command]] = 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: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[t.Union[t.Dict[str, Command], t.Sequence[Command]]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + 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: t.Dict[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = 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_multicommand(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.Union[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 + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + func: t.Optional[t.Callable] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'command(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + 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.Union[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.Optional[t.Callable] = 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 get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> t.List[str]: + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + """ + + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + #: The list of registered multi commands. + self.sources: t.List[MultiCommand] = sources or [] + + def add_source(self, multi_cmd: MultiCommand) -> None: + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> t.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 later 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: a string or list of strings that are environment variables + that should be checked. + :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. + + .. 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: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + ) -> None: + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + + 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}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.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 + """ + 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, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.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) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(self) + + 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: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """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 None: + 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: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE + + if value is None: + value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + + if value is None: + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP + + if value is None: + value = self.get_default(ctx) + 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 option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value is None: + return () if self.multiple or self.nargs == -1 else None + + def check_iter(value: t.Any) -> t.Iterator: + 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 + + if self.nargs == 1 or self.type.is_composite: + convert: t.Callable[[t.Any], t.Any] = partial( + self.type, param=self, ctx=ctx + ) + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Tuple: + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Tuple: + 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: + if value is None: + 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: + 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: + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + if self.envvar is None: + 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) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + + value = None + + if self.expose_value: + ctx.params[self.name] = value # type: ignore + + return value, args + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + pass + + def get_usage_pieces(self, ctx: Context) -> t.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) -> t.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(t.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. 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. + :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. + + .. versionchanged:: 8.1.0 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1.0 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1.0 + 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: t.Optional[t.Sequence[str]] = None, + show_default: t.Union[bool, str, None] = None, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + if is_flag is None: + if flag_value is not None: + # Implicitly a flag because flag_value was set. + is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False + else: + # Implicitly a flag because flag options were given. + is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + + if is_flag and default_is_missing and not self.required: + self.default: t.Union[t.Any, t.Callable[[], t.Any]] = False + + if flag_value is None: + flag_value = not self.default + + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag = is_flag and isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value + + # Counting + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if default_is_missing: + 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 self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError("'prompt' is not valid for non-boolean flag.") + + 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'.") + + if self.multiple and self.is_flag: + raise TypeError("'multiple' is not valid with 'is_flag', use 'count'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.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("Could not determine name for option") + + 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) -> t.Optional[t.Tuple[str, str]]: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.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()}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + extra = [] + + 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: + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) + ) + extra.append(_("env var: {var}").format(var=var_str)) + + # 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 is not None)): + 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 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 self.default else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + else: + default_string = str(default_value) + + if default_string: + extra.append(_("default: {default}").format(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.append(range_str) + + if self.required: + extra.append(_("required")) + + if extra: + extra_str = "; ".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + # If we're a non boolean flag our default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return param.flag_value # type: ignore + + return None + + return super().get_default(ctx, call=call) + + 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 be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt( + self.prompt, + default=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), + ) + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + 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.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + elif ( + self.multiple + and value is not None + 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 if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + 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 + + +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 parameter constructor. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: + if required is None: + if attrs.get("default") is not None: + required = False + else: + required = attrs.get("nargs", 1) > 0 + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") + + @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) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(self) + if not var: + var = self.name.upper() # type: ignore + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Could not determine name for argument") + 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)}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [self.make_metavar()] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/decorators.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/decorators.py new file mode 100644 index 00000000..28618dc5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/decorators.py @@ -0,0 +1,497 @@ +import inspect +import types +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 + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +FC = t.TypeVar("FC", bound=t.Union[t.Callable[..., t.Any], Command]) + + +def pass_context(f: F) -> F: + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args, **kwargs): # type: ignore + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def pass_obj(f: F) -> F: + """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, **kwargs): # type: ignore + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def make_pass_decorator( + object_type: t.Type, ensure: bool = False +) -> "t.Callable[[F], F]": + """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: F) -> F: + def new_func(*args, **kwargs): # type: ignore + ctx = get_current_context() + + 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(t.cast(F, new_func), f) + + return decorator + + +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[F], F]": + """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: F) -> F: + def new_func(*args, **kwargs): # type: ignore + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(t.cast(F, 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) + + +@t.overload +def command( + __func: t.Callable[..., t.Any], +) -> Command: + ... + + +@t.overload +def command( + name: t.Optional[str] = None, + **attrs: t.Any, +) -> t.Callable[..., Command]: + ... + + +@t.overload +def command( + name: t.Optional[str] = None, + cls: t.Type[CmdType] = ..., + **attrs: t.Any, +) -> t.Callable[..., CmdType]: + ... + + +def command( + name: t.Union[str, t.Callable[..., t.Any], None] = None, + cls: t.Optional[t.Type[Command]] = None, + **attrs: t.Any, +) -> t.Union[Command, t.Callable[..., Command]]: + 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 with + underscores replaced by dashes. If you want to change that, you can + pass the intended name as the first argument. + + 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. This defaults to the function + name with underscores replaced by dashes. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + + .. 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.Optional[t.Callable[..., t.Any]] = 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 = Command + + def decorator(f: t.Callable[..., t.Any]) -> Command: + 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__ + + cmd = cls( # type: ignore[misc] + name=name or f.__name__.lower().replace("_", "-"), # type: ignore[arg-type] + callback=f, + params=params, + **attrs, + ) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +@t.overload +def group( + __func: t.Callable[..., t.Any], +) -> Group: + ... + + +@t.overload +def group( + name: t.Optional[str] = None, + **attrs: t.Any, +) -> t.Callable[[F], Group]: + ... + + +def group( + name: t.Union[str, t.Callable[..., t.Any], None] = None, **attrs: t.Any +) -> t.Union[Group, t.Callable[[F], Group]]: + """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 attrs.get("cls") is None: + attrs["cls"] = Group + + if callable(name): + grp: t.Callable[[F], Group] = t.cast(Group, command(**attrs)) + return grp(name) + + return t.cast(Group, command(name, **attrs)) + + +def _param_memo(f: FC, 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, **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. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + """ + + def decorator(f: FC) -> FC: + ArgumentClass = attrs.pop("cls", None) or Argument + _param_memo(f, ArgumentClass(param_decls, **attrs)) + return f + + return decorator + + +def option(*param_decls: str, **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. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + """ + + def decorator(f: FC) -> FC: + # Issue 926, copy attrs, so pre-defined options can re-use the same cls= + option_attrs = attrs.copy() + OptionClass = option_attrs.pop("cls", None) or Option + _param_memo(f, OptionClass(param_decls, **option_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: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = 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``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + 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: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata # type: ignore + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + 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( + t.cast(str, 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]: + """Add a ``--help`` option which immediately prints the help page + and exits the program. + + This is usually unnecessary, as the ``--help`` option is added to + each command automatically unless ``add_help_option=False`` is + passed. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + 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["callback"] = callback + return option(*param_decls, **kwargs) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/exceptions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/exceptions.py new file mode 100644 index 00000000..9e20b3eb --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/exceptions.py @@ -0,0 +1,287 @@ +import os +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .utils import echo + +if t.TYPE_CHECKING: + from .core import Context + from .core import Parameter + + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]] +) -> t.Optional[str]: + 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) + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.Optional[t.IO] = None) -> None: + if file is None: + file = get_text_stderr() + + echo(_("Error: {message}").format(message=self.format_message()), file=file) + + +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: t.Optional["Context"] = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd = self.ctx.command if self.ctx else None + + def show(self, file: t.Optional[t.IO] = 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: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = 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: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = 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: t.Optional[str] = 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(self.param) + 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: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = 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: t.Optional["Context"] = 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 FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename = os.fsdecode(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 = code diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/formatting.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/formatting.py new file mode 100644 index 00000000..ddd2a2f8 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/formatting.py @@ -0,0 +1,301 @@ +import typing as t +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: t.Optional[int] = None + + +def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: + widths: t.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: t.Iterable[t.Tuple[str, str]], col_count: int +) -> t.Iterator[t.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: t.List[t.Tuple[int, bool, str]] = [] + buf: t.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: t.Optional[int] = None, + max_width: t.Optional[int] = None, + ) -> None: + import shutil + + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + 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 = 0 + self.buffer: t.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: t.Optional[str] = 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: t.Sequence[t.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) -> t.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) -> t.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: t.Sequence[str]) -> t.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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/globals.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/globals.py new file mode 100644 index 00000000..480058f1 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/globals.py @@ -0,0 +1,68 @@ +import typing as t +from threading import local + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": + ... + + +@t.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: + ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: + """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: t.Optional[bool] = None) -> t.Optional[bool]: + """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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/parser.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/parser.py new file mode 100644 index 00000000..2d5a2ed7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/parser.py @@ -0,0 +1,529 @@ +""" +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 +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + import typing_extensions as te + 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") + +# Sentinel value that indicates 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. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.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 `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None + + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) + 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(None) + + # 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) -> t.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: t.Optional["Context"]) -> 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)}" + + +def split_arg_string(string: str) -> t.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. + """ + 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 + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes = 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: str, 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: t.Optional[str], nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: + if self.nargs > 1: + assert value is not None + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] + self.rargs = rargs + self.order: t.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. + """ + + def __init__(self, ctx: t.Optional["Context"] = 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 = 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 = 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: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = 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: t.Optional[str], 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: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.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: t.Optional[str], 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 = None + + 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 = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we re-combinate 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 + ) -> t.Any: + nargs = option.nargs + + 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) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/shell_completion.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/shell_completion.py new file mode 100644 index 00000000..c17a8e64 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/shell_completion.py @@ -0,0 +1,580 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.Dict[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: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value = value + self.type = type + self.help = 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; +""" + +_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 +} + +compdef %(complete_func)s %(prog_name)s; +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response; + + for value in (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + set response $response $value; + end; + + 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: BaseCommand, + ctx_args: t.Dict[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("-", "_"), re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.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) -> t.Tuple[t.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: t.List[str], incomplete: str + ) -> t.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 + + def _check_version(self) -> None: + import subprocess + + output = subprocess.run( + ["bash", "-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": + raise RuntimeError( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ) + ) + else: + raise RuntimeError( + _("Couldn't detect Bash version, shell completion is not supported.") + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.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) -> t.Tuple[t.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}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + 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}" + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: t.Type[ShellComplete], name: t.Optional[str] = None +) -> None: + """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 + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """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 _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 + value = ctx.params[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: t.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 + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, ctx_args: t.Dict[str, t.Any], prog_name: str, args: t.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 + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + 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: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/termui.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/termui.py new file mode 100644 index 00000000..bfb2f5ae --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/termui.py @@ -0,0 +1,787 @@ +import inspect +import io +import itertools +import os +import sys +import typing as t +from gettext import gettext as _ + +from ._compat import isatty +from ._compat import strip_ansi +from ._compat import WIN +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.Optional[t.Any] = None, + show_choices: bool = True, + type: t.Optional[ParamType] = 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 # type: ignore + + return default + + +def prompt( + text: str, + default: t.Optional[t.Any] = None, + hide_input: bool = False, + confirmation_prompt: t.Union[bool, str] = False, + type: t.Optional[t.Union[ParamType, t.Any]] = None, + value_proc: t.Optional[t.Callable[[str], t.Any]] = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending an interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + :param show_choices: Show or hide choices if the passed type is a Choice. + For example if type is a Choice of either day or week, + show_choices is true and text is "Group by" then the + prompt will be "Group by (day, week): ". + + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: + f = hidden_prompt_func if hide_input else visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() from None + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt( + text, prompt_suffix, show_default, default, show_choices, type + ) + + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: + value = prompt_func(prompt) + if value: + break + elif default is not None: + value = default + break + try: + result = value_proc(value) + except UsageError as e: + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306 + 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: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = 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[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast(t.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) + + +def progressbar( + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = 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 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. + + .. 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 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + 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 + if WIN: + os.system("cls") + else: + sys.stdout.write("\033[2J\033[1;1H") + + +def _interpret_color( + color: t.Union[int, t.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: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = 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.Optional[t.Any] = None, + file: t.Optional[t.IO[t.AnyStr]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = 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) + + +def edit( + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: + 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. + """ + 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) + + ed.edit_file(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.Optional[t.Callable[[bool], str]] = 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() -> t.ContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: t.Optional[str] = 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/testing.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/testing.py new file mode 100644 index 00000000..e395c2ed --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/testing.py @@ -0,0 +1,479 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand + + +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) -> t.List[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> t.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: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +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: t.Optional[t.Union[str, bytes, t.IO]], charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast(t.IO, 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(t.cast(bytes, input)) + + +class Result: + """Holds the captured result of an invoked CLI script.""" + + def __init__( + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, + ): + #: The runner that created the result + self.runner = runner + #: The standard output as bytes. + self.stdout_bytes = stdout_bytes + #: The standard error as bytes, or None if not available + self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happened if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self) -> str: + """The (standard) output as unicode string.""" + return self.stdout + + @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.""" + if self.stderr_bytes is None: + raise ValueError("stderr not separately captured") + 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 stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param mix_stderr: if this is set to `False`, then stdout and stderr are + preserved as independent streams. This is useful for + Unix-philosophy apps that have predictable stdout and + noisy stderr, such that each may be measured + independently + """ + + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: + self.charset = charset + self.env = env or {} + self.echo_stdin = echo_stdin + self.mix_stderr = mix_stderr + + def get_default_prog_name(self, cli: "BaseCommand") -> 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: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: + """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: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin 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. + + .. versionchanged:: 8.0 + ``stderr`` 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) + + bytes_output = io.BytesIO() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + 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( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None + if self.mix_stderr: + sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(prompt or "") + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + return text_input.readline().rstrip("\r\n") + + @_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.Optional[t.IO] = None, color: t.Optional[bool] = 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 + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + + 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 (bytes_output, bytes_error) + 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 + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + 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``. + :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. + + .. 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 + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: t.Optional[BaseException] = 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(t.Optional[t.Union[int, t.Any]], 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() + stdout = outstreams[0].getvalue() + if self.mix_stderr: + stderr = None + else: + stderr = outstreams[1].getvalue() # type: ignore + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, os.PathLike]] = None + ) -> t.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) # type: ignore[type-var] + os.chdir(dt) + + try: + yield t.cast(str, dt) + finally: + os.chdir(cwd) + + if temp_dir is None: + try: + shutil.rmtree(dt) + except OSError: # noqa: B014 + pass diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/types.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/types.py new file mode 100644 index 00000000..b45ee53d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/types.py @@ -0,0 +1,1073 @@ +import os +import stat +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 get_filesystem_encoding +from ._compat import open_stream +from .exceptions import BadParameter +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 + + +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[t.Optional[str]] = None + + def to_info_dict(self) -> t.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: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: "Parameter") -> t.Optional[str]: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> 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) -> t.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: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = 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 + ) -> t.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 = func.__name__ + self.func = func + + def to_info_dict(self) -> t.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: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> 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: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = get_filesystem_encoding() + 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): + """The choice type allows a value to be checked against a fixed set + of supported values. All of these values have to be strings. + + You should only pass a list or tuple of choices. Other iterables + (like generators) may lead to surprising results. + + The resulting value will always be one of the originally passed choices + regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` + being specified. + + See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + """ + + name = "choice" + + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: + self.choices = choices + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> t.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 get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) + + # 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") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + # Match through normalization and case sensitivity + # first do token_normalize_func, then lowercase + # preserve original `value` to produce an accurate message in + # `self.fail` + normed_value = value + normed_choices = {choice: choice for choice in self.choices} + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(value) + normed_choices = { + ctx.token_normalize_func(normed_choice): original + for normed_choice, original in normed_choices.items() + } + + if not self.case_sensitive: + normed_value = normed_value.casefold() + normed_choices = { + normed_choice.casefold(): original + for normed_choice, original in normed_choices.items() + } + + if normed_value in normed_choices: + return normed_choices[normed_value] + + choices_str = ", ".join(map(repr, self.choices)) + self.fail( + 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), + param, + ctx, + ) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.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: t.Optional[t.Sequence[str]] = None): + self.formats = formats or ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> 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[t.Type] + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> 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: t.Optional[float] = None, + max: t.Optional[float] = 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) -> t.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: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> 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: "te.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: "te.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: t.Optional[float] = None, + max: t.Optional[float] = 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: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's 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" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: + return bool(value) + + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> 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. + + Starting with Click 2.0, 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. + """ + + name = "filename" + envvar_list_splitter = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = 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) -> t.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: t.Any) -> bool: + if self.lazy is not None: + return self.lazy + if value == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + if hasattr(value, "read") or hasattr(value, "write"): + return value + + lazy = self.resolve_lazy_flag(value) + + if lazy: + f: t.IO = t.cast( + t.IO, + LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ), + ) + + if ctx is not None: + ctx.call_on_close(f.close_intelligently) # type: ignore + + return f + + 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: # noqa: B014 + self.fail(f"'{os.fsdecode(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.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")] + + +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 ``type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter = 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: t.Optional[t.Type] = 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 = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> t.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, rv: t.Any) -> t.Any: + if self.type is not None and not isinstance(rv, self.type): + if self.type is str: + rv = os.fsdecode(rv) + elif self.type is bytes: + rv = os.fsencode(rv) + else: + rv = self.type(rv) + + return rv + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + # os.path.realpath doesn't resolve symlinks on Windows + # until Python 3.8. Use pathlib for now. + import pathlib + + rv = os.fsdecode(pathlib.Path(rv).resolve()) + + 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=os.fsdecode(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=os.fsdecode(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} '{filename}' is a directory.").format( + name=self.name.title(), filename=os.fsdecode(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=os.fsdecode(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=os.fsdecode(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=os.fsdecode(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.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: t.Sequence[t.Union[t.Type, ParamType]]) -> None: + self.types = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> t.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: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> 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)) + + +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = 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() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/utils.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/utils.py new file mode 100644 index 00000000..8283788a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/click/utils.py @@ -0,0 +1,580 @@ +import os +import re +import sys +import typing as t +from functools import update_wrapper +from types import ModuleType + +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 get_filesystem_encoding +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 + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def _posixify(name: str) -> str: + return "-".join(name.split()).lower() + + +def safecall(func: F) -> F: + """Wraps a function so that it swallows exceptions.""" + + def wrapper(*args, **kwargs): # type: ignore + try: + return func(*args, **kwargs) + except Exception: + pass + + return update_wrapper(t.cast(F, wrapper), func) + + +def make_str(value: t.Any) -> str: + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(get_filesystem_encoding()) + 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, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, + ): + self.name = filename + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + self._f: t.Optional[t.IO] + + if filename == "-": + 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: + """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: # noqa: E402 + 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, exc_value, tb): # type: ignore + self.close_intelligently() + + def __iter__(self) -> t.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO) -> None: + self._file = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> "KeepOpenFile": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> t.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.Any]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = 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() + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = 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) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: "te.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: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "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, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO: + """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 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, 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, KeepOpenFile(f)) + + return f + + +def format_filename( + filename: t.Union[str, bytes, os.PathLike], shorten: bool = False +) -> str: + """Formats a filename for user display. The main purpose of this + function is to ensure that the filename can be displayed at all. This + will decode the filename to unicode if necessary in a way that it will + not fail. Optionally, it can shorten the filename to not include the + full path to the filename. + + :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) + + return os.fsdecode(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 affect 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) -> 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: t.Optional[str] = None, _main: t.Optional[ModuleType] = 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. + if getattr(_main, "__package__", None) is 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: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/__init__.py new file mode 100644 index 00000000..3512d101 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/__init__.py @@ -0,0 +1,49 @@ +from typing import Any, Optional + +from .main import (dotenv_values, find_dotenv, get_key, load_dotenv, set_key, + unset_key) + + +def load_ipython_extension(ipython: Any) -> None: + from .ipython import load_ipython_extension + load_ipython_extension(ipython) + + +def get_cli_string( + path: Optional[str] = None, + action: Optional[str] = None, + key: Optional[str] = None, + value: Optional[str] = None, + quote: Optional[str] = None, +): + """Returns a string suitable for running as a shell script. + + Useful for converting a arguments passed to a fabric task + to be passed to a `local` or `run` command. + """ + command = ['dotenv'] + if quote: + command.append('-q %s' % quote) + if path: + command.append('-f %s' % path) + if action: + command.append(action) + if key: + command.append(key) + if value: + if ' ' in value: + command.append('"%s"' % 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/cli.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/cli.py new file mode 100644 index 00000000..b7ae24af --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/cli.py @@ -0,0 +1,164 @@ +import os +import sys +from subprocess import Popen +from typing import Any, Dict, List + +try: + import click +except ImportError: + sys.stderr.write('It seems python-dotenv is not installed with cli option. \n' + 'Run pip install "python-dotenv[cli]" to fix this.') + sys.exit(1) + +from .main import dotenv_values, get_key, set_key, unset_key +from .version import __version__ + + +@click.group() +@click.option('-f', '--file', default=os.path.join(os.getcwd(), '.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 = {} + ctx.obj['QUOTE'] = quote + ctx.obj['EXPORT'] = export + ctx.obj['FILE'] = file + + +@cli.command() +@click.pass_context +def list(ctx: click.Context) -> None: + '''Display all the stored key/value.''' + file = ctx.obj['FILE'] + if not os.path.isfile(file): + raise click.BadParameter( + 'Path "%s" does not exist.' % (file), + ctx=ctx + ) + dotenv_as_dict = dotenv_values(file) + for k, v in dotenv_as_dict.items(): + click.echo('%s=%s' % (k, v)) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +@click.argument('value', required=True) +def set(ctx: click.Context, key: Any, value: Any) -> None: + '''Store the given key/value.''' + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + export = ctx.obj['EXPORT'] + success, key, value = set_key(file, key, value, quote, export) + if success: + click.echo('%s=%s' % (key, value)) + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def get(ctx: click.Context, key: Any) -> None: + '''Retrieve the value for the given key.''' + file = ctx.obj['FILE'] + if not os.path.isfile(file): + raise click.BadParameter( + 'Path "%s" does not exist.' % (file), + ctx=ctx + ) + stored_value = get_key(file, key) + if stored_value: + click.echo(stored_value) + else: + exit(1) + + +@cli.command() +@click.pass_context +@click.argument('key', required=True) +def unset(ctx: click.Context, key: Any) -> None: + '''Removes the given key.''' + file = ctx.obj['FILE'] + quote = ctx.obj['QUOTE'] + success, key = unset_key(file, key, quote) + if success: + click.echo("Successfully removed %s" % key) + else: + exit(1) + + +@cli.command(context_settings={'ignore_unknown_options': True}) +@click.pass_context +@click.option( + "--override/--no-override", + default=True, + help="Override variables from the environment file with those from the .env file.", +) +@click.argument('commandline', nargs=-1, type=click.UNPROCESSED) +def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: + """Run command with environment variables present.""" + file = ctx.obj['FILE'] + if not os.path.isfile(file): + raise click.BadParameter( + 'Invalid value for \'-f\' "%s" does not exist.' % (file), + ctx=ctx + ) + dotenv_as_dict = { + k: v + for (k, v) in dotenv_values(file).items() + if v is not None and (override or k not in os.environ) + } + + if not commandline: + click.echo('No command given.') + exit(1) + ret = run_command(commandline, dotenv_as_dict) + exit(ret) + + +def run_command(command: List[str], env: Dict[str, str]) -> int: + """Run command in sub process. + + Runs the command in a sub process with 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 + ------- + int + The return code of the command + + """ + # copy the current environment variables and add the vales from + # `env` + cmd_env = os.environ.copy() + cmd_env.update(env) + + p = Popen(command, + universal_newlines=True, + bufsize=0, + shell=False, + env=cmd_env) + _, _ = p.communicate() + + return p.returncode + + +if __name__ == "__main__": + cli() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/ipython.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/ipython.py new file mode 100644 index 00000000..7df727cd --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/ipython.py @@ -0,0 +1,39 @@ +from IPython.core.magic import Magics, line_magic, magics_class # type: ignore +from IPython.core.magic_arguments import (argument, magic_arguments, # type: ignore + parse_argstring) # type: ignore + +from .main import find_dotenv, load_dotenv + + +@magics_class +class IPythonDotEnv(Magics): + + @magic_arguments() + @argument( + '-o', '--override', action='store_true', + help="Indicate to override existing variables" + ) + @argument( + '-v', '--verbose', action='store_true', + help="Indicate function calls to be verbose" + ) + @argument('dotenv_path', nargs='?', type=str, default='.env', + help='Search in increasingly higher folders for the `dotenv_path`') + @line_magic + def dotenv(self, line): + args = parse_argstring(self.dotenv, line) + # Locate the .env file + dotenv_path = args.dotenv_path + try: + dotenv_path = find_dotenv(dotenv_path, True, True) + except IOError: + print("cannot find .env file") + return + + # Load the .env file + load_dotenv(dotenv_path, verbose=args.verbose, override=args.override) + + +def load_ipython_extension(ipython): + """Register the %dotenv magic.""" + ipython.register_magics(IPythonDotEnv) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/main.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/main.py new file mode 100644 index 00000000..20ac61ba --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/main.py @@ -0,0 +1,373 @@ +import io +import logging +import os +import shutil +import sys +import tempfile +from collections import OrderedDict +from contextlib import contextmanager +from typing import (IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, + Union) + +from .parser import Binding, parse_stream +from .variables import parse_variables + +logger = logging.getLogger(__name__) + +if sys.version_info >= (3, 6): + _PathLike = os.PathLike +else: + _PathLike = str + + +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[Union[str, _PathLike]], + stream: Optional[IO[str]] = None, + verbose: bool = False, + encoding: Union[None, str] = None, + interpolate: bool = True, + override: bool = True, + ) -> None: + self.dotenv_path = dotenv_path # type: Optional[Union[str, _PathLike]] + self.stream = stream # type: Optional[IO[str]] + self._dict = None # type: Optional[Dict[str, Optional[str]]] + self.verbose = verbose # type: bool + self.encoding = encoding # type: Union[None, str] + self.interpolate = interpolate # type: bool + self.override = override # type: bool + + @contextmanager + def _get_stream(self) -> Iterator[IO[str]]: + if self.dotenv_path and os.path.isfile(self.dotenv_path): + with io.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. + """ + 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: Union[str, _PathLike], + 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: Union[str, _PathLike], + encoding: Optional[str], +) -> Iterator[Tuple[IO[str], IO[str]]]: + try: + if not os.path.isfile(path): + with io.open(path, "w+", encoding=encoding) as source: + source.write("") + with tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding=encoding) as dest: + with io.open(path, encoding=encoding) as source: + yield (source, dest) # type: ignore + except BaseException: + if os.path.isfile(dest.name): + os.unlink(dest.name) + raise + else: + shutil.move(dest.name, path) + + +def set_key( + dotenv_path: Union[str, _PathLike], + 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("Unknown quote_mode: {}".format(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 = 'export {}={}\n'.format(key_to_set, value_out) + else: + line_out = "{}={}\n".format(key_to_set, value_out) + + 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: Union[str, _PathLike], + 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 + + 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 = {} # type: Dict[str, Optional[str]] + + for (name, value) in values: + if value is None: + result = None + else: + atoms = parse_variables(value) + env = {} # type: 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 """ + main = __import__('__main__', None, None, fromlist=['__file__']) + return not hasattr(main, '__file__') + + if usecwd or _is_interactive() 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: + assert frame.f_back is not None + frame = frame.f_back + frame_filename = frame.f_code.co_filename + path = os.path.dirname(os.path.abspath(frame_filename)) + + for dirname in _walk_to_root(path): + check_path = os.path.join(dirname, filename) + if os.path.isfile(check_path): + return check_path + + if raise_error_if_not_found: + raise IOError('File not found') + + return '' + + +def load_dotenv( + dotenv_path: Union[str, _PathLike, None] = 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. + + - *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. Defaults to + `False`. + - *override*: whether to override the system environment variables with the variables + in `.env` file. Defaults to `False`. + - *encoding*: encoding to be used to read the file. + + If both `dotenv_path` and `stream`, `find_dotenv()` is used to find the .env file. + """ + 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: Union[str, _PathLike, None] = 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. + + - *dotenv_path*: absolute or relative path to .env file. + - *stream*: `StringIO` object with .env content, used if `dotenv_path` is `None`. + - *verbose*: whether to output a warning the .env file is missing. Defaults to + `False`. + in `.env` file. Defaults to `False`. + - *encoding*: encoding to be used to read the file. + + If both `dotenv_path` and `stream`, `find_dotenv()` is used to find the .env file. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + return DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=True, + encoding=encoding, + ).dict() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/parser.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/parser.py new file mode 100644 index 00000000..398bd49a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/parser.py @@ -0,0 +1,182 @@ +import codecs +import re +from typing import (IO, Iterator, Match, NamedTuple, Optional, # noqa:F401 + Pattern, Sequence, Tuple) + + +def make_regex(string: str, extra_flags: int = 0) -> Pattern[str]: + return re.compile(string, re.UNICODE | extra_flags) + + +_newline = make_regex(r"(\r\n|\n|\r)") +_multiline_whitespace = make_regex(r"\s*", extra_flags=re.MULTILINE) +_whitespace = make_regex(r"[^\S\r\n]*") +_export = make_regex(r"(?:export[^\S\r\n]+)?") +_single_quoted_key = make_regex(r"'([^']+)'") +_unquoted_key = make_regex(r"([^=\#\s]+)") +_equal_sign = make_regex(r"(=[^\S\r\n]*)") +_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'") +_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"') +_unquoted_value = make_regex(r"([^\r\n]*)") +_comment = make_regex(r"(?:[^\S\r\n]*#[^\r\n]*)?") +_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r|$)") +_rest_of_line = make_regex(r"[^\r\n]*(?:\r|\n|\r\n)?") +_double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]") +_single_quote_escapes = make_regex(r"\\[\\']") + + +Original = NamedTuple( + "Original", + [ + ("string", str), + ("line", int), + ], +) + +Binding = NamedTuple( + "Binding", + [ + ("key", Optional[str]), + ("value", Optional[str]), + ("original", Original), + ("error", bool), + ], +) + + +class Position: + def __init__(self, chars: int, line: int) -> None: + self.chars = chars + self.line = line + + @classmethod + def start(cls) -> "Position": + return cls(chars=0, line=1) + + def set(self, other: "Position") -> None: + self.chars = other.chars + self.line = other.line + + def advance(self, string: str) -> None: + self.chars += len(string) + self.line += len(re.findall(_newline, string)) + + +class Error(Exception): + pass + + +class Reader: + def __init__(self, stream: IO[str]) -> None: + self.string = stream.read() + self.position = Position.start() + self.mark = Position.start() + + def has_next(self) -> bool: + return self.position.chars < len(self.string) + + def set_mark(self) -> None: + self.mark.set(self.position) + + def get_marked(self) -> Original: + return Original( + string=self.string[self.mark.chars:self.position.chars], + line=self.mark.line, + ) + + def peek(self, count: int) -> str: + return self.string[self.position.chars:self.position.chars + count] + + def read(self, count: int) -> str: + result = self.string[self.position.chars:self.position.chars + count] + if len(result) < count: + raise Error("read: End of string") + self.position.advance(result) + return result + + def read_regex(self, regex: Pattern[str]) -> Sequence[str]: + match = regex.match(self.string, self.position.chars) + if match is None: + raise Error("read_regex: Pattern not found") + self.position.advance(self.string[match.start():match.end()]) + return match.groups() + + +def decode_escapes(regex: Pattern[str], string: str) -> str: + def decode_match(match: Match[str]) -> str: + return codecs.decode(match.group(0), 'unicode-escape') # type: ignore + + return regex.sub(decode_match, string) + + +def parse_key(reader: Reader) -> Optional[str]: + char = reader.peek(1) + if char == "#": + return None + elif char == "'": + (key,) = reader.read_regex(_single_quoted_key) + else: + (key,) = reader.read_regex(_unquoted_key) + return key + + +def parse_unquoted_value(reader: Reader) -> str: + (part,) = reader.read_regex(_unquoted_value) + return re.sub(r"\s+#.*", "", part).rstrip() + + +def parse_value(reader: Reader) -> str: + char = reader.peek(1) + if char == u"'": + (value,) = reader.read_regex(_single_quoted_value) + return decode_escapes(_single_quote_escapes, value) + elif char == u'"': + (value,) = reader.read_regex(_double_quoted_value) + return decode_escapes(_double_quote_escapes, value) + elif char in (u"", u"\n", u"\r"): + return u"" + else: + return parse_unquoted_value(reader) + + +def parse_binding(reader: Reader) -> Binding: + reader.set_mark() + try: + reader.read_regex(_multiline_whitespace) + if not reader.has_next(): + return Binding( + key=None, + value=None, + original=reader.get_marked(), + error=False, + ) + reader.read_regex(_export) + key = parse_key(reader) + reader.read_regex(_whitespace) + if reader.peek(1) == "=": + reader.read_regex(_equal_sign) + value = parse_value(reader) # type: Optional[str] + 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/py.typed new file mode 100644 index 00000000..7632ecf7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/variables.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/variables.py new file mode 100644 index 00000000..d77b700c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/variables.py @@ -0,0 +1,88 @@ +import re +from abc import ABCMeta +from typing import Iterator, Mapping, Optional, Pattern + +_posix_variable = re.compile( + r""" + \$\{ + (?P[^\}:]*) + (?::- + (?P[^\}]*) + )? + \} + """, + re.VERBOSE, +) # type: Pattern[str] + + +class Atom(): + __metaclass__ = ABCMeta + + def __ne__(self, other: object) -> bool: + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + return not result + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + raise NotImplementedError + + +class Literal(Atom): + def __init__(self, value: str) -> None: + self.value = value + + def __repr__(self) -> str: + return "Literal(value={})".format(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 "Variable(name={}, default={})".format(self.name, 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.groupdict()["name"] + default = match.groupdict()["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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/version.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/version.py new file mode 100644 index 00000000..5f4bb0b3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/dotenv/version.py @@ -0,0 +1 @@ +__version__ = "0.20.0" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/LICENSE new file mode 100644 index 00000000..3e92463e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/METADATA new file mode 100644 index 00000000..482fd434 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/METADATA @@ -0,0 +1,551 @@ +Metadata-Version: 2.1 +Name: fastapi +Version: 0.81.0 +Summary: FastAPI framework, high performance, easy to learn, fast to code, ready for production +Home-page: https://github.com/tiangolo/fastapi +Author: Sebastián Ramírez +Author-email: tiangolo@gmail.com +Requires-Python: >=3.6.1 +Description-Content-Type: text/markdown +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: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers +Classifier: Topic :: Internet :: WWW/HTTP +Requires-Dist: starlette==0.19.1 +Requires-Dist: pydantic >=1.6.2,!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0 +Requires-Dist: requests >=2.24.0,<3.0.0 ; extra == "all" +Requires-Dist: jinja2 >=2.11.2,<4.0.0 ; extra == "all" +Requires-Dist: python-multipart >=0.0.5,<0.0.6 ; extra == "all" +Requires-Dist: itsdangerous >=1.1.0,<3.0.0 ; extra == "all" +Requires-Dist: pyyaml >=5.3.1,<7.0.0 ; extra == "all" +Requires-Dist: ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0 ; extra == "all" +Requires-Dist: orjson >=3.2.1,<4.0.0 ; extra == "all" +Requires-Dist: email_validator >=1.1.1,<2.0.0 ; extra == "all" +Requires-Dist: uvicorn[standard] >=0.12.0,<0.18.0 ; extra == "all" +Requires-Dist: python-jose[cryptography] >=3.3.0,<4.0.0 ; extra == "dev" +Requires-Dist: passlib[bcrypt] >=1.7.2,<2.0.0 ; extra == "dev" +Requires-Dist: autoflake >=1.4.0,<2.0.0 ; extra == "dev" +Requires-Dist: flake8 >=3.8.3,<6.0.0 ; extra == "dev" +Requires-Dist: uvicorn[standard] >=0.12.0,<0.18.0 ; extra == "dev" +Requires-Dist: pre-commit >=2.17.0,<3.0.0 ; extra == "dev" +Requires-Dist: mkdocs >=1.1.2,<2.0.0 ; extra == "doc" +Requires-Dist: mkdocs-material >=8.1.4,<9.0.0 ; extra == "doc" +Requires-Dist: mdx-include >=1.4.1,<2.0.0 ; extra == "doc" +Requires-Dist: mkdocs-markdownextradata-plugin >=0.1.7,<0.3.0 ; extra == "doc" +Requires-Dist: typer >=0.4.1,<0.5.0 ; extra == "doc" +Requires-Dist: pyyaml >=5.3.1,<7.0.0 ; extra == "doc" +Requires-Dist: pytest >=6.2.4,<7.0.0 ; extra == "test" +Requires-Dist: pytest-cov >=2.12.0,<4.0.0 ; extra == "test" +Requires-Dist: mypy ==0.910 ; extra == "test" +Requires-Dist: flake8 >=3.8.3,<6.0.0 ; extra == "test" +Requires-Dist: black == 22.3.0 ; extra == "test" +Requires-Dist: isort >=5.0.6,<6.0.0 ; extra == "test" +Requires-Dist: requests >=2.24.0,<3.0.0 ; extra == "test" +Requires-Dist: httpx >=0.14.0,<0.19.0 ; extra == "test" +Requires-Dist: email_validator >=1.1.1,<2.0.0 ; extra == "test" +Requires-Dist: sqlalchemy >=1.3.18,<1.5.0 ; extra == "test" +Requires-Dist: peewee >=3.13.3,<4.0.0 ; extra == "test" +Requires-Dist: databases[sqlite] >=0.3.2,<0.6.0 ; extra == "test" +Requires-Dist: orjson >=3.2.1,<4.0.0 ; extra == "test" +Requires-Dist: ujson >=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0 ; extra == "test" +Requires-Dist: python-multipart >=0.0.5,<0.0.6 ; extra == "test" +Requires-Dist: flask >=1.1.2,<3.0.0 ; extra == "test" +Requires-Dist: anyio[trio] >=3.2.1,<4.0.0 ; extra == "test" +Requires-Dist: types-ujson ==4.2.1 ; extra == "test" +Requires-Dist: types-orjson ==3.6.2 ; extra == "test" +Requires-Dist: types-dataclasses ==0.6.5 ; extra == "test" and ( python_version<'3.7') +Project-URL: Documentation, https://fastapi.tiangolo.com/ +Provides-Extra: all +Provides-Extra: dev +Provides-Extra: doc +Provides-Extra: test + +

+ 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/tiangolo/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ 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)
+ +--- + +## **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 + +Python 3.6+ + +FastAPI stands on the shoulders of giants: + +* Starlette for the web parts. +* Pydantic for the data parts. + +## Installation + +
+ +```console +$ pip install fastapi + +---> 100% +``` + +
+ +You will also need an ASGI server, for production such as Uvicorn or Hypercorn. + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +## 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 +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [28720] +INFO: Started server process [28722] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+About the command uvicorn main:app --reload... + +The command `uvicorn main:app` refers to: + +* `main`: the file `main.py` (the Python "module"). +* `app`: the object created inside of `main.py` with the line `app = FastAPI()`. +* `--reload`: make the server restart after code changes. Only do this for development. + +
+ +### 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 server should reload automatically (because you added `--reload` to the `uvicorn` command above). + +### 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 3.6+**. + +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 `requests` 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. + +## Optional Dependencies + +Used by Pydantic: + +* ujson - for faster JSON "parsing". +* email_validator - for email validation. + +Used by Starlette: + +* requests - 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()`. +* itsdangerous - Required for `SessionMiddleware` support. +* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI). +* ujson - Required if you want to use `UJSONResponse`. + +Used by FastAPI / Starlette: + +* uvicorn - for the server that loads and serves your application. +* orjson - Required if you want to use `ORJSONResponse`. + +You can install all of these with `pip install "fastapi[all]"`. + +## License + +This project is licensed under the terms of the MIT license. + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/RECORD new file mode 100644 index 00000000..88f57d5f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/RECORD @@ -0,0 +1,91 @@ +fastapi-0.81.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +fastapi-0.81.0.dist-info/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086 +fastapi-0.81.0.dist-info/METADATA,sha256=CD9zEFul1ZeqIjXG_CDdJOsBUO--4HnPgtRpq_8jSTs,25126 +fastapi-0.81.0.dist-info/RECORD,, +fastapi-0.81.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi-0.81.0.dist-info/WHEEL,sha256=4TfKIB_xu-04bc2iKz6_zFt-gEFEEDU_31HGhqzOCE8,81 +fastapi/__init__.py,sha256=zwiRX7r_siNxDDxGccYn9vMq5KoZEHagieRbpPmpiYI,1015 +fastapi/__pycache__/__init__.cpython-37.pyc,, +fastapi/__pycache__/applications.cpython-37.pyc,, +fastapi/__pycache__/background.cpython-37.pyc,, +fastapi/__pycache__/concurrency.cpython-37.pyc,, +fastapi/__pycache__/datastructures.cpython-37.pyc,, +fastapi/__pycache__/encoders.cpython-37.pyc,, +fastapi/__pycache__/exception_handlers.cpython-37.pyc,, +fastapi/__pycache__/exceptions.cpython-37.pyc,, +fastapi/__pycache__/logger.cpython-37.pyc,, +fastapi/__pycache__/param_functions.cpython-37.pyc,, +fastapi/__pycache__/params.cpython-37.pyc,, +fastapi/__pycache__/requests.cpython-37.pyc,, +fastapi/__pycache__/responses.cpython-37.pyc,, +fastapi/__pycache__/routing.cpython-37.pyc,, +fastapi/__pycache__/staticfiles.cpython-37.pyc,, +fastapi/__pycache__/templating.cpython-37.pyc,, +fastapi/__pycache__/testclient.cpython-37.pyc,, +fastapi/__pycache__/types.cpython-37.pyc,, +fastapi/__pycache__/utils.cpython-37.pyc,, +fastapi/__pycache__/websockets.cpython-37.pyc,, +fastapi/applications.py,sha256=DGDGZRPpNW_KRKMeyoo5gl4YuE1c9uCNWigLmsqXJ30,38062 +fastapi/background.py,sha256=HtN5_pJJrOdalSbuGSMKJAPNWUU5h7rY_BXXubu7-IQ,76 +fastapi/concurrency.py,sha256=G9Q9--9t5362vQuzLzB0pL8e6BbxcVU9EpBhVyaEGJ8,1078 +fastapi/datastructures.py,sha256=oW6xuU0C-sBwbcyXI-MlBO0tSS4BSPB2lYUa1yCw8-A,1905 +fastapi/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/dependencies/__pycache__/__init__.cpython-37.pyc,, +fastapi/dependencies/__pycache__/models.cpython-37.pyc,, +fastapi/dependencies/__pycache__/utils.cpython-37.pyc,, +fastapi/dependencies/models.py,sha256=zNbioxICuOeb-9ADDVQ45hUHOC0PBtPVEfVU3f1l_nc,2494 +fastapi/dependencies/utils.py,sha256=zsbThdKoayRv0pWplZ6jWjK9ekIoix036NO_nv565xc,27373 +fastapi/encoders.py,sha256=0Zd7Ad60YMVzB5A0rcHkUZwwriY9In7FY6ziyX5BZpw,5885 +fastapi/exception_handlers.py,sha256=UVYCCe4qt5-5_NuQ3SxTXjDvOdKMHiTfcLp3RUKXhg8,912 +fastapi/exceptions.py,sha256=Wy1sP3EisJohtxr-uKoH58QumPWmqHp6cpXOD3TTPOs,1117 +fastapi/logger.py,sha256=I9NNi3ov8AcqbsbC9wl1X-hdItKgYt2XTrx1f99Zpl4,54 +fastapi/middleware/__init__.py,sha256=oQDxiFVcc1fYJUOIFvphnK7pTT5kktmfL32QXpBFvvo,58 +fastapi/middleware/__pycache__/__init__.cpython-37.pyc,, +fastapi/middleware/__pycache__/asyncexitstack.cpython-37.pyc,, +fastapi/middleware/__pycache__/cors.cpython-37.pyc,, +fastapi/middleware/__pycache__/gzip.cpython-37.pyc,, +fastapi/middleware/__pycache__/httpsredirect.cpython-37.pyc,, +fastapi/middleware/__pycache__/trustedhost.cpython-37.pyc,, +fastapi/middleware/__pycache__/wsgi.cpython-37.pyc,, +fastapi/middleware/asyncexitstack.py,sha256=72XjQmQ_tB_tTs9xOc0akXF_7TwZUPdyfc8gsN5LV8E,1197 +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-37.pyc,, +fastapi/openapi/__pycache__/constants.cpython-37.pyc,, +fastapi/openapi/__pycache__/docs.cpython-37.pyc,, +fastapi/openapi/__pycache__/models.cpython-37.pyc,, +fastapi/openapi/__pycache__/utils.cpython-37.pyc,, +fastapi/openapi/constants.py,sha256=mWxYBjED6PU-tQ9X227Qkq2SsW2cv-C1jYFKt63xxEs,107 +fastapi/openapi/docs.py,sha256=JBRaq7EEmeC-xoRSRFj6qZWQxfOZW_jvTw0r-PiKcZ4,6532 +fastapi/openapi/models.py,sha256=_XWDBU4Zlp5M9V6YI1kmXbqYKwK_xZxaqIA_DhLwqHk,11027 +fastapi/openapi/utils.py,sha256=NUrPv65N8976sqfG1kxHiHJrPYxT53NkjCWgmuyAOF0,18409 +fastapi/param_functions.py,sha256=mhV6aNZmXuf_A7rZ830o3V-DFqbonIDRs_prDTetLs4,7521 +fastapi/params.py,sha256=LRoO2H1XBBIfBGB82gHtfnXhDZiDz-7CIordN3FoU1I,10600 +fastapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/requests.py,sha256=zayepKFcienBllv3snmWI20Gk0oHNVLU4DDhqXBb4LU,142 +fastapi/responses.py,sha256=K9Gzj0E5GfwTgLiuCE-BuiXn9JdqGJHeXBMkvd8lFC8,1196 +fastapi/routing.py,sha256=gq17oux-hW8G5sr4ZhBRl-m6R3mx0jJRDHCMEMNTPcU,53459 +fastapi/security/__init__.py,sha256=bO8pNmxqVRXUjfl2mOKiVZLn0FpBQ61VUYVjmppnbJw,881 +fastapi/security/__pycache__/__init__.cpython-37.pyc,, +fastapi/security/__pycache__/api_key.cpython-37.pyc,, +fastapi/security/__pycache__/base.cpython-37.pyc,, +fastapi/security/__pycache__/http.cpython-37.pyc,, +fastapi/security/__pycache__/oauth2.cpython-37.pyc,, +fastapi/security/__pycache__/open_id_connect_url.cpython-37.pyc,, +fastapi/security/__pycache__/utils.cpython-37.pyc,, +fastapi/security/api_key.py,sha256=NbVpS9TxDOaipoZa8-SREHyMtTcM3bmy5szMiQxEX9s,2793 +fastapi/security/base.py,sha256=dl4pvbC-RxjfbWgPtCWd8MVU-7CB2SZ22rJDXVCXO6c,141 +fastapi/security/http.py,sha256=ZSy3DFKFDLa3-I4vwsY1r8hQB_VrtAXw4-fMJauZIK0,5984 +fastapi/security/oauth2.py,sha256=1NPA12T1_r2uo4iQWxJCKjUqVVdb532YDvX9e3PVpcE,8212 +fastapi/security/open_id_connect_url.py,sha256=iikzuJCz_DG44Q77VrupqSoCbJYaiXkuo_W-kdmAzeo,1145 +fastapi/security/utils.py,sha256=izlh-HBaL1VnJeOeRTQnyNgI3hgTFs73eCyLy-snb4A,266 +fastapi/staticfiles.py,sha256=iirGIt3sdY2QZXd36ijs3Cj-T0FuGFda3cd90kM9Ikw,69 +fastapi/templating.py,sha256=4zsuTWgcjcEainMJFAlW6-gnslm6AgOS1SiiDWfmQxk,76 +fastapi/testclient.py,sha256=nBvaAmX66YldReJNZXPOk1sfuo2Q6hs8bOvIaCep6LQ,66 +fastapi/types.py,sha256=r6MngTHzkZOP9lzXgduje9yeZe5EInWAzCLuRJlhIuE,118 +fastapi/utils.py,sha256=g5JDiJ4vwc-l2ffpLdkkBDEjJJz3dqZbQ2cwz-yNVwI,6594 +fastapi/websockets.py,sha256=SroIkqE-lfChvtRP3mFaNKKtD6TmePDWBZtQfgM4noo,148 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/REQUESTED b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/WHEEL new file mode 100644 index 00000000..668ba4d0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi-0.81.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.7.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/__init__.py new file mode 100644 index 00000000..3688ec89 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/__init__.py @@ -0,0 +1,24 @@ +"""FastAPI framework, high performance, easy to learn, fast to code, ready for production""" + +__version__ = "0.81.0" + +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 .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/applications.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/applications.py new file mode 100644 index 00000000..ac6050ca --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/applications.py @@ -0,0 +1,871 @@ +from enum import Enum +from typing import ( + Any, + Awaitable, + Callable, + Coroutine, + Dict, + List, + Optional, + Sequence, + Type, + Union, +) + +from fastapi import routing +from fastapi.datastructures import Default, DefaultPlaceholder +from fastapi.encoders import DictIntStrAny, SetIntStr +from fastapi.exception_handlers import ( + http_exception_handler, + request_validation_exception_handler, +) +from fastapi.exceptions import RequestValidationError +from fastapi.logger import logger +from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware +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 +from fastapi.utils import generate_unique_id +from starlette.applications import Starlette +from starlette.datastructures import State +from starlette.exceptions import ExceptionMiddleware, HTTPException +from starlette.middleware import Middleware +from starlette.middleware.errors import ServerErrorMiddleware +from starlette.requests import Request +from starlette.responses import HTMLResponse, JSONResponse, Response +from starlette.routing import BaseRoute +from starlette.types import ASGIApp, Receive, Scope, Send + + +class FastAPI(Starlette): + def __init__( + self, + *, + debug: bool = False, + routes: Optional[List[BaseRoute]] = None, + title: str = "FastAPI", + description: str = "", + version: str = "0.1.0", + openapi_url: Optional[str] = "/openapi.json", + openapi_tags: Optional[List[Dict[str, Any]]] = None, + servers: Optional[List[Dict[str, Union[str, Any]]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + default_response_class: Type[Response] = Default(JSONResponse), + docs_url: Optional[str] = "/docs", + redoc_url: Optional[str] = "/redoc", + swagger_ui_oauth2_redirect_url: Optional[str] = "/docs/oauth2-redirect", + swagger_ui_init_oauth: Optional[Dict[str, Any]] = None, + middleware: Optional[Sequence[Middleware]] = None, + exception_handlers: Optional[ + Dict[ + Union[int, Type[Exception]], + Callable[[Request, Any], Coroutine[Any, Any, Response]], + ] + ] = None, + on_startup: Optional[Sequence[Callable[[], Any]]] = None, + on_shutdown: Optional[Sequence[Callable[[], 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, + openapi_prefix: str = "", + root_path: str = "", + root_path_in_servers: bool = True, + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + callbacks: Optional[List[BaseRoute]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + swagger_ui_parameters: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + **extra: Any, + ) -> None: + self._debug: bool = debug + self.title = title + 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.extra = extra + self.openapi_version = "3.0.2" + 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.root_path = root_path or openapi_prefix + self.state: State = State() + self.dependency_overrides: Dict[Callable[..., Any], Callable[..., Any]] = {} + self.router: routing.APIRouter = routing.APIRouter( + routes=routes, + dependency_overrides_provider=self, + on_startup=on_startup, + on_shutdown=on_shutdown, + 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.user_middleware: List[Middleware] = ( + [] if middleware is None else list(middleware) + ) + self.middleware_stack: ASGIApp = self.build_middleware_stack() + self.setup() + + def build_middleware_stack(self) -> ASGIApp: + # Duplicate/override from Starlette to add AsyncExitStackMiddleware + # inside of ExceptionMiddleware, inside of custom user middlewares + debug = self.debug + error_handler = None + exception_handlers = {} + + for key, value in self.exception_handlers.items(): + if key in (500, Exception): + error_handler = value + else: + exception_handlers[key] = value + + middleware = ( + [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] + + self.user_middleware + + [ + Middleware( + ExceptionMiddleware, handlers=exception_handlers, debug=debug + ), + # Add FastAPI-specific AsyncExitStackMiddleware for dependencies with + # contextvars. + # This needs to happen after user middlewares because those create a + # new contextvars context copy by using a new AnyIO task group. + # The initial part of dependencies with yield is executed in the + # FastAPI code, inside all the middlewares, but the teardown part + # (after yield) is executed in the AsyncExitStack in this middleware, + # if the AsyncExitStack lived outside of the custom middlewares and + # contextvars were set in a dependency with yield in that internal + # contextvars context, the values would not be available in the + # outside context of the AsyncExitStack. + # By putting the middleware and the AsyncExitStack here, inside all + # user middlewares, the code before and after yield in dependencies + # with yield is executed in the same contextvars context, so all values + # set in contextvars before yield is still available after yield as + # would be expected. + # Additionally, by having this AsyncExitStack here, after the + # ExceptionMiddleware, now dependencies can catch handled exceptions, + # e.g. HTTPException, to customize the teardown code (e.g. DB session + # rollback). + Middleware(AsyncExitStackMiddleware), + ] + ) + + app = self.router + for cls, options in reversed(middleware): + app = cls(app=app, **options) + return app + + def openapi(self) -> Dict[str, Any]: + if not self.openapi_schema: + self.openapi_schema = get_openapi( + title=self.title, + version=self.version, + openapi_version=self.openapi_version, + description=self.description, + terms_of_service=self.terms_of_service, + contact=self.contact, + license_info=self.license_info, + routes=self.routes, + tags=self.openapi_tags, + servers=self.servers, + ) + 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=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=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[..., Coroutine[Any, Any, Response]], + *, + response_model: Any = 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[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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 = 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[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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 + ) -> None: + self.router.add_api_websocket_route(path, endpoint, name=name) + + def websocket( + self, path: str, name: Optional[str] = None + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_websocket_route(path, func, name=name) + return func + + return decorator + + def include_router( + self, + router: routing.APIRouter, + *, + prefix: str = "", + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + default_response_class: Type[Response] = Default(JSONResponse), + callbacks: Optional[List[BaseRoute]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + operation_id=operation_id, + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + 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, + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/background.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/background.py new file mode 100644 index 00000000..dd3bbe24 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/background.py @@ -0,0 +1 @@ +from starlette.background import BackgroundTasks as BackgroundTasks # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/concurrency.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/concurrency.py new file mode 100644 index 00000000..becac3f3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/concurrency.py @@ -0,0 +1,32 @@ +import sys +from typing import AsyncGenerator, ContextManager, TypeVar + +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, +) + +if sys.version_info >= (3, 7): + from contextlib import AsyncExitStack as AsyncExitStack + from contextlib import asynccontextmanager as asynccontextmanager +else: + from contextlib2 import AsyncExitStack as AsyncExitStack # noqa + from contextlib2 import asynccontextmanager as asynccontextmanager # noqa + + +_T = TypeVar("_T") + + +@asynccontextmanager +async def contextmanager_in_threadpool( + cm: ContextManager[_T], +) -> AsyncGenerator[_T, None]: + try: + yield await run_in_threadpool(cm.__enter__) + except Exception as e: + ok: bool = await run_in_threadpool(cm.__exit__, type(e), e, None) + if not ok: + raise e + else: + await run_in_threadpool(cm.__exit__, None, None, None) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/datastructures.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/datastructures.py new file mode 100644 index 00000000..b20a25ab --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/datastructures.py @@ -0,0 +1,56 @@ +from typing import Any, Callable, Dict, Iterable, Type, TypeVar + +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 + + +class UploadFile(StarletteUploadFile): + @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 __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update({"type": "string", "format": "binary"}) + + +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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/models.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/models.py new file mode 100644 index 00000000..443590b9 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/models.py @@ -0,0 +1,58 @@ +from typing import Any, Callable, List, Optional, Sequence + +from fastapi.security.base import SecurityBase +from pydantic.fields import ModelField + + +class SecurityRequirement: + def __init__( + self, security_scheme: SecurityBase, scopes: Optional[Sequence[str]] = None + ): + self.security_scheme = security_scheme + self.scopes = scopes + + +class Dependant: + def __init__( + self, + *, + path_params: Optional[List[ModelField]] = None, + query_params: Optional[List[ModelField]] = None, + header_params: Optional[List[ModelField]] = None, + cookie_params: Optional[List[ModelField]] = None, + body_params: Optional[List[ModelField]] = None, + dependencies: Optional[List["Dependant"]] = None, + security_schemes: Optional[List[SecurityRequirement]] = None, + 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, + ) -> None: + self.path_params = path_params or [] + self.query_params = query_params or [] + self.header_params = header_params or [] + self.cookie_params = cookie_params or [] + self.body_params = body_params or [] + self.dependencies = dependencies or [] + self.security_requirements = security_schemes or [] + self.request_param_name = request_param_name + self.websocket_param_name = websocket_param_name + self.http_connection_param_name = http_connection_param_name + self.response_param_name = response_param_name + self.background_tasks_param_name = background_tasks_param_name + self.security_scopes = security_scopes + self.security_scopes_param_name = security_scopes_param_name + self.name = name + self.call = call + self.use_cache = use_cache + # Store the path to be able to re-generate a dependable from it in overrides + self.path = path + # Save the cache key at creation to optimize performance + self.cache_key = (self.call, tuple(sorted(set(self.security_scopes or [])))) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/utils.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/utils.py new file mode 100644 index 00000000..d098b65f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/dependencies/utils.py @@ -0,0 +1,756 @@ +import dataclasses +import inspect +from contextlib import contextmanager +from copy import deepcopy +from typing import ( + Any, + Callable, + Coroutine, + Dict, + List, + Mapping, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) + +import anyio +from fastapi import params +from fastapi.concurrency import ( + AsyncExitStack, + 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_response_field, get_path_param_names +from pydantic import BaseModel, create_model +from pydantic.error_wrappers import ErrorWrapper +from pydantic.errors import MissingError +from pydantic.fields import ( + SHAPE_FROZENSET, + SHAPE_LIST, + SHAPE_SEQUENCE, + SHAPE_SET, + SHAPE_SINGLETON, + SHAPE_TUPLE, + SHAPE_TUPLE_ELLIPSIS, + FieldInfo, + ModelField, + Required, + Undefined, +) +from pydantic.schema import get_annotation_from_field_info +from pydantic.typing import ForwardRef, evaluate_forwardref +from pydantic.utils import lenient_issubclass +from starlette.background import BackgroundTasks +from starlette.concurrency import run_in_threadpool +from starlette.datastructures import FormData, Headers, QueryParams, UploadFile +from starlette.requests import HTTPConnection, Request +from starlette.responses import Response +from starlette.websockets import WebSocket + +sequence_shapes = { + SHAPE_LIST, + SHAPE_SET, + SHAPE_FROZENSET, + SHAPE_TUPLE, + SHAPE_SEQUENCE, + SHAPE_TUPLE_ELLIPSIS, +} +sequence_types = (list, set, tuple) +sequence_shape_to_type = { + SHAPE_LIST: list, + SHAPE_SET: set, + SHAPE_TUPLE: tuple, + SHAPE_SEQUENCE: list, + SHAPE_TUPLE_ELLIPSIS: list, +} + + +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 check_file_field(field: ModelField) -> None: + field_info = field.field_info + if isinstance(field_info, params.Form): + try: + # __version__ is available in both multiparts, and can be mocked + from multipart import __version__ # type: ignore + + assert __version__ + try: + # parse_options_header is only available in the right multipart + from multipart.multipart import parse_options_header # type: ignore + + assert parse_options_header + except ImportError: + logger.error(multipart_incorrect_install_error) + raise RuntimeError(multipart_incorrect_install_error) + except ImportError: + logger.error(multipart_not_installed_error) + raise RuntimeError(multipart_not_installed_error) + + +def get_param_sub_dependant( + *, param: inspect.Parameter, path: str, security_scopes: Optional[List[str]] = None +) -> Dependant: + depends: params.Depends = param.default + if depends.dependency: + dependency = depends.dependency + else: + dependency = param.annotation + return get_sub_dependant( + depends=depends, + dependency=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_schemes=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_params(dependant: Dependant) -> List[ModelField]: + flat_dependant = get_flat_dependant(dependant, skip_repeats=True) + return ( + flat_dependant.path_params + + flat_dependant.query_params + + flat_dependant.header_params + + flat_dependant.cookie_params + ) + + +def is_scalar_field(field: ModelField) -> bool: + field_info = field.field_info + if not ( + field.shape == SHAPE_SINGLETON + and not lenient_issubclass(field.type_, BaseModel) + and not lenient_issubclass(field.type_, sequence_types + (dict,)) + and not dataclasses.is_dataclass(field.type_) + and not isinstance(field_info, params.Body) + ): + return False + if field.sub_fields: + if not all(is_scalar_field(f) for f in field.sub_fields): + return False + return True + + +def is_scalar_sequence_field(field: ModelField) -> bool: + if (field.shape in sequence_shapes) and not lenient_issubclass( + field.type_, BaseModel + ): + if field.sub_fields is not None: + for sub_field in field.sub_fields: + if not is_scalar_field(sub_field): + return False + return True + if lenient_issubclass(field.type_, sequence_types): + return True + return False + + +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, globalns), + ) + for param in signature.parameters.values() + ] + typed_signature = inspect.Signature(typed_params) + return typed_signature + + +def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any: + annotation = param.annotation + if isinstance(annotation, str): + annotation = ForwardRef(annotation) + annotation = evaluate_forwardref(annotation, globalns, globalns) + return annotation + + +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(): + if isinstance(param.default, params.Depends): + sub_dependant = get_param_sub_dependant( + param=param, path=path, security_scopes=security_scopes + ) + dependant.dependencies.append(sub_dependant) + continue + if add_non_field_param_to_dependency(param=param, dependant=dependant): + continue + param_field = get_param_field( + param=param, default_field_info=params.Query, param_name=param_name + ) + if param_name in path_param_names: + assert is_scalar_field( + field=param_field + ), "Path params must be of one of the supported types" + ignore_default = not isinstance(param.default, params.Path) + param_field = get_param_field( + param=param, + param_name=param_name, + default_field_info=params.Path, + force_type=params.ParamTypes.path, + ignore_default=ignore_default, + ) + add_param_to_fields(field=param_field, dependant=dependant) + elif is_scalar_field(field=param_field): + add_param_to_fields(field=param_field, dependant=dependant) + elif isinstance( + param.default, (params.Query, params.Header) + ) and is_scalar_sequence_field(param_field): + add_param_to_fields(field=param_field, dependant=dependant) + else: + field_info = param_field.field_info + assert isinstance( + field_info, params.Body + ), f"Param: {param_field.name} can only be a request body, using Body()" + dependant.body_params.append(param_field) + return dependant + + +def add_non_field_param_to_dependency( + *, param: inspect.Parameter, dependant: Dependant +) -> Optional[bool]: + if lenient_issubclass(param.annotation, Request): + dependant.request_param_name = param.name + return True + elif lenient_issubclass(param.annotation, WebSocket): + dependant.websocket_param_name = param.name + return True + elif lenient_issubclass(param.annotation, HTTPConnection): + dependant.http_connection_param_name = param.name + return True + elif lenient_issubclass(param.annotation, Response): + dependant.response_param_name = param.name + return True + elif lenient_issubclass(param.annotation, BackgroundTasks): + dependant.background_tasks_param_name = param.name + return True + elif lenient_issubclass(param.annotation, SecurityScopes): + dependant.security_scopes_param_name = param.name + return True + return None + + +def get_param_field( + *, + param: inspect.Parameter, + param_name: str, + default_field_info: Type[params.Param] = params.Param, + force_type: Optional[params.ParamTypes] = None, + ignore_default: bool = False, +) -> ModelField: + default_value: Any = Undefined + had_schema = False + if not param.default == param.empty and ignore_default is False: + default_value = param.default + if isinstance(default_value, FieldInfo): + had_schema = True + field_info = default_value + default_value = field_info.default + if ( + isinstance(field_info, params.Param) + and getattr(field_info, "in_", None) is None + ): + field_info.in_ = default_field_info.in_ + if force_type: + field_info.in_ = force_type # type: ignore + else: + field_info = default_field_info(default=default_value) + required = True + if default_value is Required or ignore_default: + required = True + default_value = None + elif default_value is not Undefined: + required = False + annotation: Any = Any + if not param.annotation == param.empty: + annotation = param.annotation + annotation = get_annotation_from_field_info(annotation, field_info, param_name) + 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 = create_response_field( + name=param.name, + type_=annotation, + default=default_value, + alias=alias, + required=required, + field_info=field_info, + ) + if not had_schema and not is_scalar_field(field=field): + field.field_info = params.Body(field_info.default) + if not had_schema and lenient_issubclass(field.type_, UploadFile): + field.field_info = params.File(field_info.default) + + return field + + +def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: + field_info = cast(params.Param, field.field_info) + 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 + call = getattr(call, "__call__", None) + return inspect.iscoroutinefunction(call) + + +def is_async_gen_callable(call: Callable[..., Any]) -> bool: + if inspect.isasyncgenfunction(call): + return True + call = getattr(call, "__call__", None) + return inspect.isasyncgenfunction(call) + + +def is_gen_callable(call: Callable[..., Any]) -> bool: + if inspect.isgeneratorfunction(call): + return True + call = getattr(call, "__call__", None) + return inspect.isgeneratorfunction(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) + + +async def solve_dependencies( + *, + request: Union[Request, WebSocket], + dependant: Dependant, + body: Optional[Union[Dict[str, Any], FormData]] = None, + background_tasks: Optional[BackgroundTasks] = None, + response: Optional[Response] = None, + dependency_overrides_provider: Optional[Any] = None, + dependency_cache: Optional[Dict[Tuple[Callable[..., Any], Tuple[str]], Any]] = None, +) -> Tuple[ + Dict[str, Any], + List[ErrorWrapper], + Optional[BackgroundTasks], + Response, + Dict[Tuple[Callable[..., Any], Tuple[str]], Any], +]: + values: Dict[str, Any] = {} + errors: List[ErrorWrapper] = [] + 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, + ) + ( + sub_values, + sub_errors, + background_tasks, + _, # the subdependency returns the same response we have + sub_dependency_cache, + ) = solved_result + dependency_cache.update(sub_dependency_cache) + if sub_errors: + errors.extend(sub_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): + stack = request.scope.get("fastapi_astack") + assert isinstance(stack, AsyncExitStack) + solved = await solve_generator( + call=call, stack=stack, sub_values=sub_values + ) + elif is_coroutine_callable(call): + solved = await call(**sub_values) + else: + solved = await run_in_threadpool(call, **sub_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 + required_params=dependant.body_params, received_body=body + ) + 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 values, errors, background_tasks, response, dependency_cache + + +def request_params_to_args( + required_params: Sequence[ModelField], + received_params: Union[Mapping[str, Any], QueryParams, Headers], +) -> Tuple[Dict[str, Any], List[ErrorWrapper]]: + values = {} + errors = [] + for field in required_params: + if is_scalar_sequence_field(field) and isinstance( + received_params, (QueryParams, Headers) + ): + value = received_params.getlist(field.alias) or field.default + else: + value = received_params.get(field.alias) + field_info = field.field_info + assert isinstance( + field_info, params.Param + ), "Params must be subclasses of Param" + if value is None: + if field.required: + errors.append( + ErrorWrapper( + MissingError(), loc=(field_info.in_.value, field.alias) + ) + ) + else: + values[field.name] = deepcopy(field.default) + continue + v_, errors_ = field.validate( + value, values, loc=(field_info.in_.value, field.alias) + ) + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + else: + values[field.name] = v_ + return values, errors + + +async def request_body_to_args( + required_params: List[ModelField], + received_body: Optional[Union[Dict[str, Any], FormData]], +) -> Tuple[Dict[str, Any], List[ErrorWrapper]]: + values = {} + errors = [] + if required_params: + field = required_params[0] + field_info = field.field_info + embed = getattr(field_info, "embed", None) + field_alias_omitted = len(required_params) == 1 and not embed + if field_alias_omitted: + received_body = {field.alias: received_body} + + for field in required_params: + loc: Tuple[str, ...] + if field_alias_omitted: + loc = ("body",) + else: + loc = ("body", field.alias) + + value: Optional[Any] = None + if received_body is not None: + if ( + field.shape in sequence_shapes or field.type_ in sequence_types + ) and isinstance(received_body, FormData): + value = received_body.getlist(field.alias) + else: + try: + value = received_body.get(field.alias) + except AttributeError: + errors.append(get_missing_field_error(loc)) + continue + if ( + value is None + or (isinstance(field_info, params.Form) and value == "") + or ( + isinstance(field_info, params.Form) + and field.shape in sequence_shapes + and len(value) == 0 + ) + ): + if field.required: + errors.append(get_missing_field_error(loc)) + else: + values[field.name] = deepcopy(field.default) + continue + if ( + isinstance(field_info, params.File) + and lenient_issubclass(field.type_, bytes) + and isinstance(value, UploadFile) + ): + value = await value.read() + elif ( + field.shape in sequence_shapes + and isinstance(field_info, params.File) + and lenient_issubclass(field.type_, bytes) + and isinstance(value, sequence_types) + ): + results: List[Union[bytes, str]] = [] + + async def process_fn( + fn: Callable[[], Coroutine[Any, Any, Any]] + ) -> None: + result = await fn() + results.append(result) + + async with anyio.create_task_group() as tg: + for sub_value in value: + tg.start_soon(process_fn, sub_value.read) + value = sequence_shape_to_type[field.shape](results) + + v_, errors_ = field.validate(value, values, loc=loc) + + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + else: + values[field.name] = v_ + return values, errors + + +def get_missing_field_error(loc: Tuple[str, ...]) -> ErrorWrapper: + missing_field_error = ErrorWrapper(MissingError(), loc=loc) + return missing_field_error + + +def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]: + flat_dependant = get_flat_dependant(dependant) + if not flat_dependant.body_params: + return None + first_param = flat_dependant.body_params[0] + field_info = first_param.field_info + embed = getattr(field_info, "embed", None) + body_param_names_set = {param.name for param in flat_dependant.body_params} + if len(body_param_names_set) == 1 and not embed: + check_file_field(first_param) + return first_param + # If one field requires to embed, all have to be embedded + # in case a sub-dependency is evaluated with a single unique body field + # That is combined (embedded) with other body fields + for param in flat_dependant.body_params: + setattr(param.field_info, "embed", True) + model_name = "Body_" + name + BodyModel: Type[BaseModel] = create_model(model_name) + for f in flat_dependant.body_params: + BodyModel.__fields__[f.name] = f + required = any(True for f in flat_dependant.body_params if f.required) + + BodyFieldInfo_kwargs: Dict[str, Any] = dict(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 = [ + getattr(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_response_field( + name="body", + type_=BodyModel, + required=required, + alias="body", + field_info=BodyFieldInfo(**BodyFieldInfo_kwargs), + ) + check_file_field(final_field) + return final_field diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/encoders.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/encoders.py new file mode 100644 index 00000000..f64e4b86 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/encoders.py @@ -0,0 +1,167 @@ +import dataclasses +from collections import defaultdict +from enum import Enum +from pathlib import PurePath +from types import GeneratorType +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union + +from pydantic import BaseModel +from pydantic.json import ENCODERS_BY_TYPE + +SetIntStr = Set[Union[int, str]] +DictIntStrAny = Dict[Union[int, str], Any] + + +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: Any, + include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + by_alias: bool = True, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None, + sqlalchemy_safe: bool = True, +) -> Any: + 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): + encoder = getattr(obj.__config__, "json_encoders", {}) + if custom_encoder: + encoder.update(custom_encoder) + obj_dict = obj.dict( + include=include, # type: ignore # in Pydantic + exclude=exclude, # type: ignore # in Pydantic + 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, + custom_encoder=encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + if dataclasses.is_dataclass(obj): + obj_dict = dataclasses.asdict(obj) + return jsonable_encoder( + obj_dict, + exclude_none=exclude_none, + exclude_defaults=exclude_defaults, + 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, 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)): + 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) + 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exception_handlers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exception_handlers.py new file mode 100644 index 00000000..2b286d71 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exception_handlers.py @@ -0,0 +1,25 @@ +from fastapi.encoders import jsonable_encoder +from fastapi.exceptions import RequestValidationError +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import JSONResponse +from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY + + +async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse: + headers = getattr(exc, "headers", None) + if headers: + return JSONResponse( + {"detail": exc.detail}, status_code=exc.status_code, headers=headers + ) + else: + return JSONResponse({"detail": exc.detail}, status_code=exc.status_code) + + +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())}, + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exceptions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exceptions.py new file mode 100644 index 00000000..0f50acc6 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/exceptions.py @@ -0,0 +1,36 @@ +from typing import Any, Dict, Optional, Sequence, Type + +from pydantic import BaseModel, ValidationError, create_model +from pydantic.error_wrappers import ErrorList +from starlette.exceptions import HTTPException as StarletteHTTPException + + +class HTTPException(StarletteHTTPException): + def __init__( + self, + status_code: int, + detail: Any = None, + headers: Optional[Dict[str, Any]] = None, + ) -> None: + super().__init__(status_code=status_code, detail=detail, headers=headers) + + +RequestErrorModel: Type[BaseModel] = create_model("Request") +WebSocketErrorModel: Type[BaseModel] = create_model("WebSocket") + + +class FastAPIError(RuntimeError): + """ + A generic, FastAPI-specific error. + """ + + +class RequestValidationError(ValidationError): + def __init__(self, errors: Sequence[ErrorList], *, body: Any = None) -> None: + self.body = body + super().__init__(errors, RequestErrorModel) + + +class WebSocketRequestValidationError(ValidationError): + def __init__(self, errors: Sequence[ErrorList]) -> None: + super().__init__(errors, WebSocketErrorModel) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/logger.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/logger.py new file mode 100644 index 00000000..5b2c4ad5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/logger.py @@ -0,0 +1,3 @@ +import logging + +logger = logging.getLogger("fastapi") diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/__init__.py new file mode 100644 index 00000000..620296d5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/__init__.py @@ -0,0 +1 @@ +from starlette.middleware import Middleware as Middleware diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/asyncexitstack.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/asyncexitstack.py new file mode 100644 index 00000000..503a68ac --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/asyncexitstack.py @@ -0,0 +1,28 @@ +from typing import Optional + +from fastapi.concurrency import AsyncExitStack +from starlette.types import ASGIApp, Receive, Scope, Send + + +class AsyncExitStackMiddleware: + def __init__(self, app: ASGIApp, context_name: str = "fastapi_astack") -> None: + self.app = app + self.context_name = context_name + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if AsyncExitStack: + dependency_exception: Optional[Exception] = None + async with AsyncExitStack() as stack: + scope[self.context_name] = stack + try: + await self.app(scope, receive, send) + except Exception as e: + dependency_exception = e + raise e + if dependency_exception: + # This exception was possibly handled by the dependency but it should + # still bubble up so that the ServerErrorMiddleware can return a 500 + # or the ExceptionMiddleware can catch and handle any other exceptions + raise dependency_exception + else: + await self.app(scope, receive, send) # pragma: no cover diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/cors.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/cors.py new file mode 100644 index 00000000..8dfaad0d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/cors.py @@ -0,0 +1 @@ +from starlette.middleware.cors import CORSMiddleware as CORSMiddleware # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/gzip.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/gzip.py new file mode 100644 index 00000000..bbeb2cc7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/gzip.py @@ -0,0 +1 @@ +from starlette.middleware.gzip import GZipMiddleware as GZipMiddleware # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/httpsredirect.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/httpsredirect.py new file mode 100644 index 00000000..b7a3d8e0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/httpsredirect.py @@ -0,0 +1,3 @@ +from starlette.middleware.httpsredirect import ( # noqa + HTTPSRedirectMiddleware as HTTPSRedirectMiddleware, +) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/trustedhost.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/trustedhost.py new file mode 100644 index 00000000..08d7e035 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/trustedhost.py @@ -0,0 +1,3 @@ +from starlette.middleware.trustedhost import ( # noqa + TrustedHostMiddleware as TrustedHostMiddleware, +) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/wsgi.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/wsgi.py new file mode 100644 index 00000000..c4c6a797 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/middleware/wsgi.py @@ -0,0 +1 @@ +from starlette.middleware.wsgi import WSGIMiddleware as WSGIMiddleware # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/constants.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/constants.py new file mode 100644 index 00000000..1897ad75 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/constants.py @@ -0,0 +1,2 @@ +METHODS_WITH_BODY = {"GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"} +REF_PREFIX = "#/components/schemas/" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/docs.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/docs.py new file mode 100644 index 00000000..bf335118 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/docs.py @@ -0,0 +1,203 @@ +import json +from typing import Any, Dict, Optional + +from fastapi.encoders import jsonable_encoder +from starlette.responses import HTMLResponse + +swagger_ui_default_parameters = { + "dom_id": "#swagger-ui", + "layout": "BaseLayout", + "deepLinking": True, + "showExtensions": True, + "showCommonExtensions": True, +} + + +def get_swagger_ui_html( + *, + openapi_url: str, + title: str, + swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui-bundle.js", + swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@4/swagger-ui.css", + swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png", + oauth2_redirect_url: Optional[str] = None, + init_oauth: Optional[Dict[str, Any]] = None, + swagger_ui_parameters: Optional[Dict[str, Any]] = None, +) -> HTMLResponse: + current_swagger_ui_parameters = swagger_ui_default_parameters.copy() + if swagger_ui_parameters: + current_swagger_ui_parameters.update(swagger_ui_parameters) + + html = f""" + + + + + + {title} + + +
+
+ + + + + + """ + return HTMLResponse(html) + + +def get_redoc_html( + *, + openapi_url: str, + title: str, + redoc_js_url: str = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js", + redoc_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png", + with_google_fonts: bool = True, +) -> HTMLResponse: + html = f""" + + + + {title} + + + + """ + if with_google_fonts: + html += """ + + """ + html += f""" + + + + + + + + + + + """ + return HTMLResponse(html) + + +def get_swagger_ui_oauth2_redirect_html() -> HTMLResponse: + # 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/models.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/models.py new file mode 100644 index 00000000..35aa1672 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/models.py @@ -0,0 +1,406 @@ +from enum import Enum +from typing import Any, Callable, Dict, Iterable, List, Optional, Union + +from fastapi.logger import logger +from pydantic import AnyUrl, BaseModel, Field + +try: + import email_validator # type: ignore + + 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) + + +class Contact(BaseModel): + name: Optional[str] = None + url: Optional[AnyUrl] = None + email: Optional[EmailStr] = None + + class Config: + extra = "allow" + + +class License(BaseModel): + name: str + url: Optional[AnyUrl] = None + + class Config: + extra = "allow" + + +class Info(BaseModel): + title: str + description: Optional[str] = None + termsOfService: Optional[str] = None + contact: Optional[Contact] = None + license: Optional[License] = None + version: str + + class Config: + extra = "allow" + + +class ServerVariable(BaseModel): + enum: Optional[List[str]] = None + default: str + description: Optional[str] = None + + class Config: + extra = "allow" + + +class Server(BaseModel): + url: Union[AnyUrl, str] + description: Optional[str] = None + variables: Optional[Dict[str, ServerVariable]] = None + + class Config: + extra = "allow" + + +class Reference(BaseModel): + ref: str = Field(alias="$ref") + + +class Discriminator(BaseModel): + propertyName: str + mapping: Optional[Dict[str, str]] = None + + +class XML(BaseModel): + name: Optional[str] = None + namespace: Optional[str] = None + prefix: Optional[str] = None + attribute: Optional[bool] = None + wrapped: Optional[bool] = None + + class Config: + extra = "allow" + + +class ExternalDocumentation(BaseModel): + description: Optional[str] = None + url: AnyUrl + + class Config: + extra = "allow" + + +class Schema(BaseModel): + ref: Optional[str] = Field(default=None, alias="$ref") + title: Optional[str] = None + multipleOf: Optional[float] = None + maximum: Optional[float] = None + exclusiveMaximum: Optional[float] = None + minimum: Optional[float] = None + exclusiveMinimum: Optional[float] = None + maxLength: Optional[int] = Field(default=None, gte=0) + minLength: Optional[int] = Field(default=None, gte=0) + pattern: Optional[str] = None + maxItems: Optional[int] = Field(default=None, gte=0) + minItems: Optional[int] = Field(default=None, gte=0) + uniqueItems: Optional[bool] = None + maxProperties: Optional[int] = Field(default=None, gte=0) + minProperties: Optional[int] = Field(default=None, gte=0) + required: Optional[List[str]] = None + enum: Optional[List[Any]] = None + type: Optional[str] = None + allOf: Optional[List["Schema"]] = None + oneOf: Optional[List["Schema"]] = None + anyOf: Optional[List["Schema"]] = None + not_: Optional["Schema"] = Field(default=None, alias="not") + items: Optional[Union["Schema", List["Schema"]]] = None + properties: Optional[Dict[str, "Schema"]] = None + additionalProperties: Optional[Union["Schema", Reference, bool]] = None + description: Optional[str] = None + format: Optional[str] = None + default: Optional[Any] = None + nullable: Optional[bool] = None + discriminator: Optional[Discriminator] = None + readOnly: Optional[bool] = None + writeOnly: Optional[bool] = None + xml: Optional[XML] = None + externalDocs: Optional[ExternalDocumentation] = None + example: Optional[Any] = None + deprecated: Optional[bool] = None + + class Config: + extra: str = "allow" + + +class Example(BaseModel): + summary: Optional[str] = None + description: Optional[str] = None + value: Optional[Any] = None + externalValue: Optional[AnyUrl] = None + + class Config: + extra = "allow" + + +class ParameterInType(Enum): + query = "query" + header = "header" + path = "path" + cookie = "cookie" + + +class Encoding(BaseModel): + 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 Config: + extra = "allow" + + +class MediaType(BaseModel): + 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 Config: + extra = "allow" + + +class ParameterBase(BaseModel): + 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 Config: + extra = "allow" + + +class Parameter(ParameterBase): + name: str + in_: ParameterInType = Field(alias="in") + + +class Header(ParameterBase): + pass + + +class RequestBody(BaseModel): + description: Optional[str] = None + content: Dict[str, MediaType] + required: Optional[bool] = None + + class Config: + extra = "allow" + + +class Link(BaseModel): + 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 Config: + extra = "allow" + + +class Response(BaseModel): + 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 Config: + extra = "allow" + + +class Operation(BaseModel): + 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: Dict[str, Union[Response, Any]] + 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 Config: + extra = "allow" + + +class PathItem(BaseModel): + 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 Config: + extra = "allow" + + +class SecuritySchemeType(Enum): + apiKey = "apiKey" + http = "http" + oauth2 = "oauth2" + openIdConnect = "openIdConnect" + + +class SecurityBase(BaseModel): + type_: SecuritySchemeType = Field(alias="type") + description: Optional[str] = None + + class Config: + extra = "allow" + + +class APIKeyIn(Enum): + query = "query" + header = "header" + cookie = "cookie" + + +class APIKey(SecurityBase): + type_ = Field(SecuritySchemeType.apiKey, alias="type") + in_: APIKeyIn = Field(alias="in") + name: str + + +class HTTPBase(SecurityBase): + type_ = Field(SecuritySchemeType.http, alias="type") + scheme: str + + +class HTTPBearer(HTTPBase): + scheme = "bearer" + bearerFormat: Optional[str] = None + + +class OAuthFlow(BaseModel): + refreshUrl: Optional[str] = None + scopes: Dict[str, str] = {} + + class Config: + extra = "allow" + + +class OAuthFlowImplicit(OAuthFlow): + authorizationUrl: str + + +class OAuthFlowPassword(OAuthFlow): + tokenUrl: str + + +class OAuthFlowClientCredentials(OAuthFlow): + tokenUrl: str + + +class OAuthFlowAuthorizationCode(OAuthFlow): + authorizationUrl: str + tokenUrl: str + + +class OAuthFlows(BaseModel): + implicit: Optional[OAuthFlowImplicit] = None + password: Optional[OAuthFlowPassword] = None + clientCredentials: Optional[OAuthFlowClientCredentials] = None + authorizationCode: Optional[OAuthFlowAuthorizationCode] = None + + class Config: + extra = "allow" + + +class OAuth2(SecurityBase): + type_ = Field(SecuritySchemeType.oauth2, alias="type") + flows: OAuthFlows + + +class OpenIdConnect(SecurityBase): + type_ = Field(SecuritySchemeType.openIdConnect, alias="type") + openIdConnectUrl: str + + +SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer] + + +class Components(BaseModel): + 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 + + class Config: + extra = "allow" + + +class Tag(BaseModel): + name: str + description: Optional[str] = None + externalDocs: Optional[ExternalDocumentation] = None + + class Config: + extra = "allow" + + +class OpenAPI(BaseModel): + openapi: str + info: Info + servers: Optional[List[Server]] = None + # Using Any for Specification Extensions + paths: Dict[str, Union[PathItem, Any]] + components: Optional[Components] = None + security: Optional[List[Dict[str, List[str]]]] = None + tags: Optional[List[Tag]] = None + externalDocs: Optional[ExternalDocumentation] = None + + class Config: + extra = "allow" + + +Schema.update_forward_refs() +Operation.update_forward_refs() +Encoding.update_forward_refs() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/utils.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/utils.py new file mode 100644 index 00000000..4d5741f3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/openapi/utils.py @@ -0,0 +1,441 @@ +import http.client +import inspect +import warnings +from enum import Enum +from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast + +from fastapi import routing +from fastapi.datastructures import DefaultPlaceholder +from fastapi.dependencies.models import Dependant +from fastapi.dependencies.utils import get_flat_dependant, get_flat_params +from fastapi.encoders import jsonable_encoder +from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX +from fastapi.openapi.models import OpenAPI +from fastapi.params import Body, Param +from fastapi.responses import Response +from fastapi.utils import ( + deep_dict_update, + generate_operation_id_for_path, + get_model_definitions, + is_body_allowed_for_status_code, +) +from pydantic import BaseModel +from pydantic.fields import ModelField, Undefined +from pydantic.schema import ( + field_schema, + get_flat_models_from_fields, + get_model_name_map, +) +from pydantic.utils import lenient_issubclass +from starlette.responses import JSONResponse +from starlette.routing import BaseRoute +from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY + +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( + *, + all_route_params: Sequence[ModelField], + model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str], +) -> List[Dict[str, Any]]: + parameters = [] + for param in all_route_params: + field_info = param.field_info + field_info = cast(Param, field_info) + if not field_info.include_in_schema: + continue + parameter = { + "name": param.alias, + "in": field_info.in_.value, + "required": param.required, + "schema": field_schema( + param, model_name_map=model_name_map, ref_prefix=REF_PREFIX + )[0], + } + if field_info.description: + parameter["description"] = field_info.description + if field_info.examples: + parameter["examples"] = jsonable_encoder(field_info.examples) + elif field_info.example != Undefined: + parameter["example"] = jsonable_encoder(field_info.example) + if field_info.deprecated: + parameter["deprecated"] = field_info.deprecated + parameters.append(parameter) + return parameters + + +def get_openapi_operation_request_body( + *, + body_field: Optional[ModelField], + model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str], +) -> Optional[Dict[str, Any]]: + if not body_field: + return None + assert isinstance(body_field, ModelField) + body_schema, _, _ = field_schema( + body_field, model_name_map=model_name_map, ref_prefix=REF_PREFIX + ) + 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.examples: + request_media_content["examples"] = jsonable_encoder(field_info.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) + 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, model_name_map: Dict[type, str], operation_ids: Set[str] +) -> 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) + all_route_params = get_flat_params(route.dependant) + operation_parameters = get_openapi_operation_parameters( + all_route_params=all_route_params, model_name_map=model_name_map + ) + parameters.extend(operation_parameters) + if parameters: + operation["parameters"] = list( + { + (param["in"], param["name"]): param for param in parameters + }.values() + ) + if method in METHODS_WITH_BODY: + request_body_oai = get_openapi_operation_request_body( + body_field=route.body_field, model_name_map=model_name_map + ) + 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, + model_name_map=model_name_map, + operation_ids=operation_ids, + ) + 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, _, _ = field_schema( + route.response_field, + model_name_map=model_name_map, + ref_prefix=REF_PREFIX, + ) + 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, _, _ = field_schema( + field, model_name_map=model_name_map, ref_prefix=REF_PREFIX + ) + 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) + 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_flat_models_from_routes( + routes: Sequence[BaseRoute], +) -> Set[Union[Type[BaseModel], Type[Enum]]]: + body_fields_from_routes: List[ModelField] = [] + responses_from_routes: List[ModelField] = [] + request_fields_from_routes: List[ModelField] = [] + callback_flat_models: Set[Union[Type[BaseModel], Type[Enum]]] = set() + 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 |= get_flat_models_from_routes(route.callbacks) + params = get_flat_params(route.dependant) + request_fields_from_routes.extend(params) + + flat_models = callback_flat_models | get_flat_models_from_fields( + body_fields_from_routes + responses_from_routes + request_fields_from_routes, + known_models=set(), + ) + return flat_models + + +def get_openapi( + *, + title: str, + version: str, + openapi_version: str = "3.0.2", + description: Optional[str] = None, + routes: Sequence[BaseRoute], + 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, +) -> Dict[str, Any]: + info: Dict[str, Any] = {"title": title, "version": version} + 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]] = {} + operation_ids: Set[str] = set() + flat_models = get_flat_models_from_routes(routes) + model_name_map = get_model_name_map(flat_models) + definitions = get_model_definitions( + flat_models=flat_models, model_name_map=model_name_map + ) + for route in routes: + if isinstance(route, routing.APIRoute): + result = get_openapi_path( + route=route, model_name_map=model_name_map, operation_ids=operation_ids + ) + 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) + if definitions: + components["schemas"] = {k: definitions[k] for k in sorted(definitions)} + if components: + output["components"] = components + output["paths"] = paths + if tags: + output["tags"] = tags + return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/param_functions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/param_functions.py new file mode 100644 index 00000000..1932ef06 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/param_functions.py @@ -0,0 +1,290 @@ +from typing import Any, Callable, Dict, Optional, Sequence + +from fastapi import params +from pydantic.fields import Undefined + + +def Path( # noqa: N802 + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Path( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Query( # noqa: N802 + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Query( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Header( # noqa: N802 + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Header( + default=default, + alias=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, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Cookie( # noqa: N802 + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Cookie( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Body( # noqa: N802 + default: Any = Undefined, + *, + embed: bool = False, + media_type: str = "application/json", + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + **extra: Any, +) -> Any: + return params.Body( + default=default, + embed=embed, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +def Form( # noqa: N802 + default: Any = Undefined, + *, + media_type: str = "application/x-www-form-urlencoded", + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + **extra: Any, +) -> Any: + return params.Form( + default=default, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +def File( # noqa: N802 + default: Any = Undefined, + *, + media_type: str = "multipart/form-data", + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + **extra: Any, +) -> Any: + return params.File( + default=default, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +def Depends( # noqa: N802 + dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True +) -> Any: + return params.Depends(dependency=dependency, use_cache=use_cache) + + +def Security( # noqa: N802 + dependency: Optional[Callable[..., Any]] = None, + *, + scopes: Optional[Sequence[str]] = None, + use_cache: bool = True, +) -> Any: + return params.Security(dependency=dependency, scopes=scopes, use_cache=use_cache) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/params.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/params.py new file mode 100644 index 00000000..5395b98a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/params.py @@ -0,0 +1,380 @@ +from enum import Enum +from typing import Any, Callable, Dict, Optional, Sequence + +from pydantic.fields import FieldInfo, Undefined + + +class ParamTypes(Enum): + query = "query" + header = "header" + path = "path" + cookie = "cookie" + + +class Param(FieldInfo): + in_: ParamTypes + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + self.deprecated = deprecated + self.example = example + self.examples = examples + self.include_in_schema = include_in_schema + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + **extra, + ) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.default})" + + +class Path(Param): + in_ = ParamTypes.path + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + self.in_ = self.in_ + super().__init__( + default=..., + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Query(Param): + in_ = ParamTypes.query + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Header(Param): + in_ = ParamTypes.header + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + self.convert_underscores = convert_underscores + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Cookie(Param): + in_ = ParamTypes.cookie + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Body(FieldInfo): + def __init__( + self, + default: Any = Undefined, + *, + embed: bool = False, + media_type: str = "application/json", + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + **extra: Any, + ): + self.embed = embed + self.media_type = media_type + self.example = example + self.examples = examples + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + **extra, + ) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.default})" + + +class Form(Body): + def __init__( + self, + default: Any, + *, + media_type: str = "application/x-www-form-urlencoded", + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + **extra: Any, + ): + super().__init__( + default=default, + embed=True, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +class File(Form): + def __init__( + self, + default: Any, + *, + media_type: str = "multipart/form-data", + alias: Optional[str] = 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, + regex: Optional[str] = None, + example: Any = Undefined, + examples: Optional[Dict[str, Any]] = None, + **extra: Any, + ): + super().__init__( + default=default, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/requests.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/requests.py new file mode 100644 index 00000000..d16552c0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/responses.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/responses.py new file mode 100644 index 00000000..6cd79315 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/responses.py @@ -0,0 +1,34 @@ +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): + 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): + media_type = "application/json" + + def render(self, content: Any) -> bytes: + assert orjson is not None, "orjson must be installed to use ORJSONResponse" + return orjson.dumps(content) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/routing.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/routing.py new file mode 100644 index 00000000..1ac4b388 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/routing.py @@ -0,0 +1,1237 @@ +import asyncio +import dataclasses +import email.message +import inspect +import json +from enum import Enum, IntEnum +from typing import ( + Any, + Callable, + Coroutine, + Dict, + List, + Optional, + Sequence, + Set, + Tuple, + Type, + Union, +) + +from fastapi import params +from fastapi.datastructures import Default, DefaultPlaceholder +from fastapi.dependencies.models import Dependant +from fastapi.dependencies.utils import ( + get_body_field, + get_dependant, + get_parameterless_sub_dependant, + solve_dependencies, +) +from fastapi.encoders import DictIntStrAny, SetIntStr, jsonable_encoder +from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError +from fastapi.types import DecoratedCallable +from fastapi.utils import ( + create_cloned_field, + create_response_field, + generate_unique_id, + get_value_or_default, + is_body_allowed_for_status_code, +) +from pydantic import BaseModel +from pydantic.error_wrappers import ErrorWrapper, ValidationError +from pydantic.fields import ModelField, Undefined +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 +from starlette.routing import Mount as Mount # noqa +from starlette.routing import ( + compile_path, + get_name, + request_response, + websocket_session, +) +from starlette.status import WS_1008_POLICY_VIOLATION +from starlette.types import ASGIApp, Scope +from starlette.websockets import WebSocket + + +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(res.__config__, "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 res.dict( + 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 + + +async def serialize_response( + *, + field: Optional[ModelField] = None, + response_content: Any, + include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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 = [] + 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( # type: ignore[misc] + field.validate, response_content, {}, loc=("response",) + ) + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + if errors: + raise ValidationError(errors, field.type_) + 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[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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, +) -> 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: + try: + body: Any = None + if body_field: + if is_body_form: + body = await request.form() + 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: + raise RequestValidationError( + [ErrorWrapper(e, ("body", e.pos))], body=e.doc + ) from e + except HTTPException: + raise + except Exception as e: + raise HTTPException( + status_code=400, detail="There was an error parsing the body" + ) from e + solved_result = await solve_dependencies( + request=request, + dependant=dependant, + body=body, + dependency_overrides_provider=dependency_overrides_provider, + ) + values, errors, background_tasks, sub_response, _ = solved_result + if errors: + raise RequestValidationError(errors, body=body) + else: + raw_response = await run_endpoint_function( + dependant=dependant, values=values, is_coroutine=is_coroutine + ) + + if isinstance(raw_response, Response): + if raw_response.background is None: + raw_response.background = background_tasks + return raw_response + response_args: Dict[str, Any] = {"background": 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 sub_response.status_code + ) + if current_status_code is not None: + response_args["status_code"] = current_status_code + if sub_response.status_code: + response_args["status_code"] = sub_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(status_code): + response.body = b"" + response.headers.raw.extend(sub_response.headers.raw) + return response + + return app + + +def get_websocket_app( + dependant: Dependant, dependency_overrides_provider: Optional[Any] = None +) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: + async def app(websocket: WebSocket) -> None: + solved_result = await solve_dependencies( + request=websocket, + dependant=dependant, + dependency_overrides_provider=dependency_overrides_provider, + ) + values, errors, _, _2, _3 = solved_result + if errors: + await websocket.close(code=WS_1008_POLICY_VIOLATION) + raise WebSocketRequestValidationError(errors) + assert dependant.call is not None, "dependant.call must be a function" + await dependant.call(**values) + + return app + + +class APIWebSocketRoute(routing.WebSocketRoute): + def __init__( + self, + path: str, + endpoint: Callable[..., Any], + *, + name: Optional[str] = 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.dependant = get_dependant(path=path, call=self.endpoint) + self.app = websocket_session( + get_websocket_app( + dependant=self.dependant, + dependency_overrides_provider=dependency_overrides_provider, + ) + ) + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + + 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 = 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[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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 + 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_response_field( + name=response_name, type_=self.response_model + ) + # 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 be always created. + 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 + if dependencies: + self.dependencies = list(dependencies) + else: + self.dependencies = [] + 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_response_field(name=response_name, type_=model) + 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.body_field = get_body_field(dependant=self.dependant, name=self.unique_id) + 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, + ) + + 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): + def __init__( + self, + *, + prefix: str = "", + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + default_response_class: Type[Response] = Default(JSONResponse), + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + callbacks: Optional[List[BaseRoute]] = None, + routes: Optional[List[routing.BaseRoute]] = None, + redirect_slashes: bool = True, + default: Optional[ASGIApp] = None, + dependency_overrides_provider: Optional[Any] = None, + route_class: Type[APIRoute] = APIRoute, + on_startup: Optional[Sequence[Callable[[], Any]]] = None, + on_shutdown: Optional[Sequence[Callable[[], Any]]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + super().__init__( + routes=routes, + redirect_slashes=redirect_slashes, + default=default, + on_startup=on_startup, + on_shutdown=on_shutdown, + ) + 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 []) 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 add_api_route( + self, + path: str, + endpoint: Callable[..., Any], + *, + response_model: Any = 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[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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 = 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[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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 + ) -> None: + route = APIWebSocketRoute( + self.prefix + path, + endpoint=endpoint, + name=name, + dependency_overrides_provider=self.dependency_overrides_provider, + ) + self.routes.append(route) + + def websocket( + self, path: str, name: Optional[str] = None + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_websocket_route(path, func, name=name) + return func + + return decorator + + def include_router( + self, + router: "APIRouter", + *, + prefix: str = "", + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + default_response_class: Type[Response] = Default(JSONResponse), + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + callbacks: Optional[List[BaseRoute]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + 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") + name = getattr(r, "name", "unknown") + if path is not None and not path: + raise Exception( + 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): + self.add_api_websocket_route( + prefix + route.path, route.endpoint, 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) + + def get( + self, + path: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + 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: str, + *, + response_model: Any = 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, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = 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]: + + 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, + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/__init__.py new file mode 100644 index 00000000..3aa6bf21 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/api_key.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/api_key.py new file mode 100644 index 00000000..36ab60e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/api_key.py @@ -0,0 +1,92 @@ +from typing import Optional + +from fastapi.openapi.models import APIKey, APIKeyIn +from fastapi.security.base import SecurityBase +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.status import HTTP_403_FORBIDDEN + + +class APIKeyBase(SecurityBase): + pass + + +class APIKeyQuery(APIKeyBase): + def __init__( + self, + *, + name: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.query}, 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: str = 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): + def __init__( + self, + *, + name: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.header}, 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: str = 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): + def __init__( + self, + *, + name: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.cookie}, 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/base.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/base.py new file mode 100644 index 00000000..c43555de --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/http.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/http.py new file mode 100644 index 00000000..1b473c69 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/http.py @@ -0,0 +1,165 @@ +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 + + +class HTTPBasicCredentials(BaseModel): + username: str + password: str + + +class HTTPAuthorizationCredentials(BaseModel): + scheme: str + credentials: str + + +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: str = 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): + def __init__( + self, + *, + scheme_name: Optional[str] = None, + realm: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = 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: str = 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"} + invalid_user_credentials_exc = HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Invalid authentication credentials", + headers=unauthorized_headers, + ) + 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 + try: + data = b64decode(param).decode("ascii") + except (ValueError, UnicodeDecodeError, binascii.Error): + raise invalid_user_credentials_exc + username, separator, password = data.partition(":") + if not separator: + raise invalid_user_credentials_exc + return HTTPBasicCredentials(username=username, password=password) + + +class HTTPBearer(HTTPBase): + def __init__( + self, + *, + bearerFormat: Optional[str] = None, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = 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: str = 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): + def __init__( + self, + *, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = 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: str = 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/oauth2.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/oauth2.py new file mode 100644 index 00000000..653c3010 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/oauth2.py @@ -0,0 +1,220 @@ +from typing import Any, Dict, List, Optional, Union + +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 + + +class OAuth2PasswordRequestForm: + """ + This is a dependency class, use it like: + + @app.post("/login") + def login(form_data: OAuth2PasswordRequestForm = Depends()): + data = form_data.parse() + print(data.username) + print(data.password) + for scope in data.scopes: + print(scope) + if data.client_id: + print(data.client_id) + if data.client_secret: + print(data.client_secret) + return data + + + It creates the following Form request parameters in your endpoint: + + grant_type: 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. + 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: str = Form(default=None, regex="password"), + username: str = Form(), + password: str = Form(), + scope: str = Form(default=""), + client_id: Optional[str] = Form(default=None), + client_secret: Optional[str] = Form(default=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, use it like: + + @app.post("/login") + def login(form_data: OAuth2PasswordRequestFormStrict = Depends()): + data = form_data.parse() + print(data.username) + print(data.password) + for scope in data.scopes: + print(scope) + if data.client_id: + print(data.client_id) + if data.client_secret: + print(data.client_secret) + return data + + + It creates the following Form request parameters in your endpoint: + + 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: str = Form(regex="password"), + username: str = Form(), + password: str = Form(), + scope: str = Form(default=""), + client_id: Optional[str] = Form(default=None), + client_secret: Optional[str] = Form(default=None), + ): + super().__init__( + grant_type=grant_type, + username=username, + password=password, + scope=scope, + client_id=client_id, + client_secret=client_secret, + ) + + +class OAuth2(SecurityBase): + def __init__( + self, + *, + flows: Union[OAuthFlowsModel, Dict[str, Dict[str, Any]]] = OAuthFlowsModel(), + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True + ): + self.model = OAuth2Model(flows=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: str = 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): + def __init__( + self, + tokenUrl: str, + scheme_name: Optional[str] = None, + scopes: Optional[Dict[str, str]] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + if not scopes: + scopes = {} + flows = OAuthFlowsModel(password={"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: str = 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): + def __init__( + self, + authorizationUrl: str, + tokenUrl: str, + refreshUrl: Optional[str] = None, + scheme_name: Optional[str] = None, + scopes: Optional[Dict[str, str]] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + if not scopes: + scopes = {} + flows = OAuthFlowsModel( + authorizationCode={ + "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: str = 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: + def __init__(self, scopes: Optional[List[str]] = None): + self.scopes = scopes or [] + self.scope_str = " ".join(self.scopes) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/open_id_connect_url.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/open_id_connect_url.py new file mode 100644 index 00000000..dfe9f7b2 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/open_id_connect_url.py @@ -0,0 +1,34 @@ +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 + + +class OpenIdConnect(SecurityBase): + def __init__( + self, + *, + openIdConnectUrl: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = 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: str = 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/utils.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/utils.py new file mode 100644 index 00000000..2da0dd20 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/security/utils.py @@ -0,0 +1,8 @@ +from typing import Tuple + + +def get_authorization_scheme_param(authorization_header_value: str) -> Tuple[str, str]: + if not authorization_header_value: + return "", "" + scheme, _, param = authorization_header_value.partition(" ") + return scheme, param diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/staticfiles.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/staticfiles.py new file mode 100644 index 00000000..299015d4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/staticfiles.py @@ -0,0 +1 @@ +from starlette.staticfiles import StaticFiles as StaticFiles # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/templating.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/templating.py new file mode 100644 index 00000000..0cb86848 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/templating.py @@ -0,0 +1 @@ +from starlette.templating import Jinja2Templates as Jinja2Templates # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/testclient.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/testclient.py new file mode 100644 index 00000000..4012406a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/testclient.py @@ -0,0 +1 @@ +from starlette.testclient import TestClient as TestClient # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/types.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/types.py new file mode 100644 index 00000000..e0bca463 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/types.py @@ -0,0 +1,3 @@ +from typing import Any, Callable, TypeVar + +DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any]) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/utils.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/utils.py new file mode 100644 index 00000000..0ced0125 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/utils.py @@ -0,0 +1,189 @@ +import functools +import re +import warnings +from dataclasses import is_dataclass +from enum import Enum +from typing import TYPE_CHECKING, Any, Dict, Optional, Set, Type, Union, cast + +import fastapi +from fastapi.datastructures import DefaultPlaceholder, DefaultType +from fastapi.openapi.constants import REF_PREFIX +from pydantic import BaseConfig, BaseModel, create_model +from pydantic.class_validators import Validator +from pydantic.fields import FieldInfo, ModelField, UndefinedType +from pydantic.schema import model_process_schema +from pydantic.utils import lenient_issubclass + +if TYPE_CHECKING: # pragma: nocover + from .routing import APIRoute + + +def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool: + if status_code is None: + return True + current_status_code = int(status_code) + return not (current_status_code < 200 or current_status_code in {204, 304}) + + +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] + definitions[model_name] = m_schema + return definitions + + +def get_path_param_names(path: str) -> Set[str]: + return set(re.findall("{(.*?)}", path)) + + +def create_response_field( + name: str, + type_: Type[Any], + class_validators: Optional[Dict[str, Validator]] = None, + default: Optional[Any] = None, + required: Union[bool, UndefinedType] = True, + model_config: Type[BaseConfig] = BaseConfig, + field_info: Optional[FieldInfo] = None, + alias: Optional[str] = None, +) -> ModelField: + """ + Create a new response field. Raises if type_ is invalid. + """ + class_validators = class_validators or {} + field_info = field_info or FieldInfo() + + response_field = functools.partial( + ModelField, + name=name, + type_=type_, + class_validators=class_validators, + default=default, + required=required, + model_config=model_config, + alias=alias, + ) + + try: + return response_field(field_info=field_info) + except RuntimeError: + raise fastapi.exceptions.FastAPIError( + f"Invalid args for response field! Hint: check that {type_} is a valid pydantic field type" + ) + + +def create_cloned_field( + field: ModelField, + *, + cloned_types: Optional[Dict[Type[BaseModel], Type[BaseModel]]] = None, +) -> ModelField: + # _cloned_types has already cloned types, to support recursive models + if cloned_types is None: + cloned_types = {} + 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_response_field(name=field.name, type_=use_type) + new_field.has_alias = field.has_alias + new_field.alias = field.alias + new_field.class_validators = field.class_validators + new_field.default = field.default + new_field.required = field.required + new_field.model_config = field.model_config + new_field.field_info = field.field_info + new_field.allow_none = field.allow_none + new_field.validate_always = field.validate_always + if field.sub_fields: + new_field.sub_fields = [ + create_cloned_field(sub_field, cloned_types=cloned_types) + for sub_field in field.sub_fields + ] + if field.key_field: + new_field.key_field = create_cloned_field( + field.key_field, cloned_types=cloned_types + ) + new_field.validators = field.validators + new_field.pre_validators = field.pre_validators + new_field.post_validators = field.post_validators + new_field.parse_json = field.parse_json + new_field.shape = field.shape + new_field.populate_validators() + 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 = name + path + operation_id = re.sub(r"\W", "_", operation_id) + operation_id = operation_id + "_" + method.lower() + return operation_id + + +def generate_unique_id(route: "APIRoute") -> str: + operation_id = route.name + route.path_format + operation_id = re.sub(r"\W", "_", operation_id) + assert route.methods + operation_id = 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/websockets.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/websockets.py new file mode 100644 index 00000000..bed672ac --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/fastapi/websockets.py @@ -0,0 +1,2 @@ +from starlette.websockets import WebSocket as WebSocket # noqa +from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/LICENSE.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/LICENSE.txt new file mode 100644 index 00000000..8f080eae --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/METADATA new file mode 100644 index 00000000..8c77b40c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/METADATA @@ -0,0 +1,197 @@ +Metadata-Version: 2.1 +Name: h11 +Version: 0.13.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 +Platform: UNKNOWN +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.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: System :: Networking +Requires-Python: >=3.6 +License-File: LICENSE.txt +Requires-Dist: dataclasses ; python_version < "3.7" +Requires-Dist: typing-extensions ; python_version < "3.8" + +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.6-3.9) 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/RECORD new file mode 100644 index 00000000..98ad52af --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/RECORD @@ -0,0 +1,52 @@ +h11-0.13.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +h11-0.13.0.dist-info/LICENSE.txt,sha256=N9tbuFkm2yikJ6JYZ_ELEjIAOuob5pzLhRE4rbjm82E,1124 +h11-0.13.0.dist-info/METADATA,sha256=Fd9foEJycn0gUB9YsXul6neMlYnEU0MRQ8IUBsSOHxE,8245 +h11-0.13.0.dist-info/RECORD,, +h11-0.13.0.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92 +h11-0.13.0.dist-info/top_level.txt,sha256=F7dC4jl3zeh8TGHEPaWJrMbeuoWbS379Gwdi-Yvdcis,4 +h11/__init__.py,sha256=iO1KzkSO42yZ6ffg-VMgbx_ZVTWGUY00nRYEWn-s3kY,1507 +h11/__pycache__/__init__.cpython-37.pyc,, +h11/__pycache__/_abnf.cpython-37.pyc,, +h11/__pycache__/_connection.cpython-37.pyc,, +h11/__pycache__/_events.cpython-37.pyc,, +h11/__pycache__/_headers.cpython-37.pyc,, +h11/__pycache__/_readers.cpython-37.pyc,, +h11/__pycache__/_receivebuffer.cpython-37.pyc,, +h11/__pycache__/_state.cpython-37.pyc,, +h11/__pycache__/_util.cpython-37.pyc,, +h11/__pycache__/_version.cpython-37.pyc,, +h11/__pycache__/_writers.cpython-37.pyc,, +h11/_abnf.py,sha256=tMKqgOEkTHHp8sPd_gmU9Qowe_yXXrihct63RX2zJsg,4637 +h11/_connection.py,sha256=udHjqEO1fOcQUKa3hYIw88DMeoyG4fxiIXKjgE4DwJw,26480 +h11/_events.py,sha256=LEfuvg1AbhHaVRwxCd0I-pFn9-ezUOaoL8o2Kvy1PBA,11816 +h11/_headers.py,sha256=tRwZuFy5Wj4Yi9VVad_s7EqwCgeN6O3TIbcHd5CN_GI,10230 +h11/_readers.py,sha256=TWWoSbLVBfYGzD5dunReTd2QCxz466wjwu-4Fkzk_sQ,8370 +h11/_receivebuffer.py,sha256=xrspsdsNgWFxRfQcTXxR8RrdjRXXTK0Io5cQYWpJ1Ws,5252 +h11/_state.py,sha256=F8MPHIFMJV3kUPYR3YjrjqjJ1AYp_FZ38UwGr0855lE,13184 +h11/_util.py,sha256=LWkkjXyJaFlAy6Lt39w73UStklFT5ovcvo0TkY7RYuk,4888 +h11/_version.py,sha256=ye-8iNs3P1TB71VRGlNQe2OxnAe-RupjozAMywAS5z8,686 +h11/_writers.py,sha256=7WBTXyJqFAUqqmLl5adGF8_7UVQdOVa2phL8s8csljI,5063 +h11/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 +h11/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +h11/tests/__pycache__/__init__.cpython-37.pyc,, +h11/tests/__pycache__/helpers.cpython-37.pyc,, +h11/tests/__pycache__/test_against_stdlib_http.cpython-37.pyc,, +h11/tests/__pycache__/test_connection.cpython-37.pyc,, +h11/tests/__pycache__/test_events.cpython-37.pyc,, +h11/tests/__pycache__/test_headers.cpython-37.pyc,, +h11/tests/__pycache__/test_helpers.cpython-37.pyc,, +h11/tests/__pycache__/test_io.cpython-37.pyc,, +h11/tests/__pycache__/test_receivebuffer.cpython-37.pyc,, +h11/tests/__pycache__/test_state.cpython-37.pyc,, +h11/tests/__pycache__/test_util.cpython-37.pyc,, +h11/tests/data/test-file,sha256=ZJ03Rqs98oJw29OHzJg7LlMzyGQaRAY0r3AqBeM2wVU,65 +h11/tests/helpers.py,sha256=a1EVG_p7xU4wRsa3tMPTRxuaKCmretok9sxXWvqfmQA,3355 +h11/tests/test_against_stdlib_http.py,sha256=cojCHgHXFQ8gWhNlEEwl3trmOpN-5uDukRoHnElqo3A,3995 +h11/tests/test_connection.py,sha256=ZbPLDPclKvjgjAhgk-WlCPBaf17c4XUIV2tpaW08jOI,38720 +h11/tests/test_events.py,sha256=LPVLbcV-NvPNK9fW3rraR6Bdpz1hAlsWubMtNaJ5gHg,4657 +h11/tests/test_headers.py,sha256=qd8T1Zenuz5GbD6wklSJ5G8VS7trrYgMV0jT-SMvqg8,5612 +h11/tests/test_helpers.py,sha256=kAo0CEM4LGqmyyP2ZFmhsyq3UFJqoFfAbzu3hbWreRM,794 +h11/tests/test_io.py,sha256=gXFSKpcx6n3-Ld0Y8w5kBkom1LZsCq3uHtqdotQ3S2c,16243 +h11/tests/test_receivebuffer.py,sha256=3jGbeJM36Akqg_pAhPb7XzIn2NS6RhPg-Ryg8Eu6ytk,3454 +h11/tests/test_state.py,sha256=rqll9WqFsJPE0zSrtCn9LH659mPKsDeXZ-DwXwleuBQ,8928 +h11/tests/test_util.py,sha256=ZWdRng_P-JP-cnvmcBhazBxfyWmEKBB0NLrDy5eq3h0,2970 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/WHEEL new file mode 100644 index 00000000..5bad85fd --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/top_level.txt new file mode 100644 index 00000000..0d24def7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11-0.13.0.dist-info/top_level.txt @@ -0,0 +1 @@ +h11 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/__init__.py new file mode 100644 index 00000000..989e92c3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_abnf.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_abnf.py new file mode 100644 index 00000000..e6d49e1e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_abnf.py @@ -0,0 +1,129 @@ +# We use native strings for all the re patterns, to take advantage of string +# formatting, and then convert to bytestrings when compiling the final re +# objects. + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#whitespace +# OWS = *( SP / HTAB ) +# ; optional whitespace +OWS = r"[ \t]*" + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.token.separators +# token = 1*tchar +# +# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" +# / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" +# / DIGIT / ALPHA +# ; any VCHAR, except delimiters +token = r"[-!#$%&'*+.^_`|~0-9a-zA-Z]+" + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#header.fields +# field-name = token +field_name = token + +# The standard says: +# +# field-value = *( field-content / obs-fold ) +# field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] +# field-vchar = VCHAR / obs-text +# obs-fold = CRLF 1*( SP / HTAB ) +# ; obsolete line folding +# ; see Section 3.2.4 +# +# https://tools.ietf.org/html/rfc5234#appendix-B.1 +# +# VCHAR = %x21-7E +# ; visible (printing) characters +# +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.quoted-string +# obs-text = %x80-FF +# +# However, the standard definition of field-content is WRONG! It disallows +# fields containing a single visible character surrounded by whitespace, +# e.g. "foo a bar". +# +# See: https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189 +# +# So our definition of field_content attempts to fix it up... +# +# Also, we allow lots of control characters, because apparently people assume +# that they're legal in practice (e.g., google analytics makes cookies with +# \x01 in them!): +# https://github.com/python-hyper/h11/issues/57 +# We still don't allow NUL or whitespace, because those are often treated as +# meta-characters and letting them through can lead to nasty issues like SSRF. +vchar = r"[\x21-\x7e]" +vchar_or_obs_text = r"[^\x00\s]" +field_vchar = vchar_or_obs_text +field_content = r"{field_vchar}+(?:[ \t]+{field_vchar}+)*".format(**globals()) + +# We handle obs-fold at a different level, and our fixed-up field_content +# already grows to swallow the whole value, so ? instead of * +field_value = r"({field_content})?".format(**globals()) + +# header-field = field-name ":" OWS field-value OWS +header_field = ( + r"(?P{field_name})" + 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"\r\n".format(**globals()) +) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_connection.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_connection.py new file mode 100644 index 00000000..d11386f0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_connection.py @@ -0,0 +1,631 @@ +# This contains the main Connection class. Everything in h11 revolves around +# this. +from typing import Any, Callable, cast, Dict, List, Optional, 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("expected CLIENT or SERVER, not {!r}".format(our_role)) + 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 + + # 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[Sentinel]]: + 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() # type: ignore[attr-defined] + else: + event = ConnectionClosed() + if event is None: + event = NEED_DATA + return event # type: ignore[no-any-return] + + def next_event(self) -> Union[Event, Type[Sentinel]]: + """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 + + 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_events.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_events.py new file mode 100644 index 00000000..075bf8a4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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, field +from typing import Any, cast, Dict, 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_headers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_headers.py new file mode 100644 index 00000000..acc45969 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_headers.py @@ -0,0 +1,278 @@ +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 + + +# 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(br"[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 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_readers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_readers.py new file mode 100644 index 00000000..a036d790 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_readers.py @@ -0,0 +1,249 @@ +# 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")) + +# Remember that this has to run in O(n) time -- so e.g. the bytearray cast is +# critical. +obs_fold_re = re.compile(br"[ \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): + 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; if + # this is >0 then we discard that many bytes before resuming regular + # de-chunkification. + self._bytes_to_discard = 0 + 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 > 0: + data = buf.maybe_extract_at_most(self._bytes_to_discard) + if data is None: + return None + self._bytes_to_discard -= len(data) + if self._bytes_to_discard > 0: + return None + # else, fall through and read some more + assert self._bytes_to_discard == 0 + 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 = 2 + 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[Sentinel, Tuple[Sentinel, 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_receivebuffer.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_receivebuffer.py new file mode 100644 index 00000000..e5c4e08a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_state.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_state.py new file mode 100644 index 00000000..27907688 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_state.py @@ -0,0 +1,363 @@ +################################################################ +# 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: {}, + }, +} + +# NB: there are also some special-case state-triggered transitions hard-coded +# into _fire_state_triggered_transitions below. +STATE_TRIGGERED_TRANSITIONS = { + # (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 {} event without a pending proposal".format( + server_switch_event + ) + ) + _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) # type: ignore + + if self.states == start_states: + # Fixed point reached + return + + def start_next_cycle(self) -> None: + if self.states != {CLIENT: DONE, SERVER: DONE}: + raise LocalProtocolError( + "not in a reusable state. self.states={}".format(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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_util.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_util.py new file mode 100644 index 00000000..67184452 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_version.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_version.py new file mode 100644 index 00000000..75d42886 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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.13.0" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_writers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/_writers.py new file mode 100644 index 00000000..90a8dc0a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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[Sentinel, Sentinel], 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/py.typed new file mode 100644 index 00000000..f5642f79 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/py.typed @@ -0,0 +1 @@ +Marker diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/data/test-file b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/data/test-file new file mode 100644 index 00000000..d0be0a6c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/data/test-file @@ -0,0 +1 @@ +92b12bc045050b55b848d37167a1a63947c364579889ce1d39788e45e9fac9e5 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/helpers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/helpers.py new file mode 100644 index 00000000..571be444 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/helpers.py @@ -0,0 +1,101 @@ +from typing import cast, List, Type, Union, ValuesView + +from .._connection import Connection, NEED_DATA, PAUSED +from .._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from .._state import CLIENT, CLOSED, DONE, MUST_CLOSE, SERVER +from .._util import Sentinel + +try: + from typing import Literal +except ImportError: + from typing_extensions import Literal # type: ignore + + +def get_all_events(conn: Connection) -> List[Event]: + got_events = [] + while True: + event = conn.next_event() + if event in (NEED_DATA, PAUSED): + break + event = cast(Event, event) + got_events.append(event) + if type(event) is ConnectionClosed: + break + return got_events + + +def receive_and_get(conn: Connection, data: bytes) -> List[Event]: + conn.receive_data(data) + return get_all_events(conn) + + +# Merges adjacent Data events, converts payloads to bytestrings, and removes +# chunk boundaries. +def normalize_data_events(in_events: List[Event]) -> List[Event]: + out_events: List[Event] = [] + for event in in_events: + if type(event) is Data: + event = Data(data=bytes(event.data), chunk_start=False, chunk_end=False) + if out_events and type(out_events[-1]) is type(event) is Data: + out_events[-1] = Data( + data=out_events[-1].data + event.data, + chunk_start=out_events[-1].chunk_start, + chunk_end=out_events[-1].chunk_end, + ) + else: + out_events.append(event) + return out_events + + +# Given that we want to write tests that push some events through a Connection +# and check that its state updates appropriately... we might as make a habit +# of pushing them through two Connections with a fake network link in +# between. +class ConnectionPair: + def __init__(self) -> None: + self.conn = {CLIENT: Connection(CLIENT), SERVER: Connection(SERVER)} + self.other = {CLIENT: SERVER, SERVER: CLIENT} + + @property + def conns(self) -> ValuesView[Connection]: + return self.conn.values() + + # expect="match" if expect=send_events; expect=[...] to say what expected + def send( + self, + role: Type[Sentinel], + send_events: Union[List[Event], Event], + expect: Union[List[Event], Event, Literal["match"]] = "match", + ) -> bytes: + if not isinstance(send_events, list): + send_events = [send_events] + data = b"" + closed = False + for send_event in send_events: + new_data = self.conn[role].send(send_event) + if new_data is None: + closed = True + else: + data += new_data + # send uses b"" to mean b"", and None to mean closed + # receive uses b"" to mean closed, and None to mean "try again" + # so we have to translate between the two conventions + if data: + self.conn[self.other[role]].receive_data(data) + if closed: + self.conn[self.other[role]].receive_data(b"") + got_events = get_all_events(self.conn[self.other[role]]) + if expect == "match": + expect = send_events + if not isinstance(expect, list): + expect = [expect] + assert got_events == expect + return data diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_against_stdlib_http.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_against_stdlib_http.py new file mode 100644 index 00000000..d2ee1314 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_against_stdlib_http.py @@ -0,0 +1,115 @@ +import json +import os.path +import socket +import socketserver +import threading +from contextlib import closing, contextmanager +from http.server import SimpleHTTPRequestHandler +from typing import Callable, Generator +from urllib.request import urlopen + +import h11 + + +@contextmanager +def socket_server( + handler: Callable[..., socketserver.BaseRequestHandler] +) -> Generator[socketserver.TCPServer, None, None]: + httpd = socketserver.TCPServer(("127.0.0.1", 0), handler) + thread = threading.Thread( + target=httpd.serve_forever, kwargs={"poll_interval": 0.01} + ) + thread.daemon = True + try: + thread.start() + yield httpd + finally: + httpd.shutdown() + + +test_file_path = os.path.join(os.path.dirname(__file__), "data/test-file") +with open(test_file_path, "rb") as f: + test_file_data = f.read() + + +class SingleMindedRequestHandler(SimpleHTTPRequestHandler): + def translate_path(self, path: str) -> str: + return test_file_path + + +def test_h11_as_client() -> None: + with socket_server(SingleMindedRequestHandler) as httpd: + with closing(socket.create_connection(httpd.server_address)) as s: + c = h11.Connection(h11.CLIENT) + + s.sendall( + c.send( # type: ignore[arg-type] + h11.Request( + method="GET", target="/foo", headers=[("Host", "localhost")] + ) + ) + ) + s.sendall(c.send(h11.EndOfMessage())) # type: ignore[arg-type] + + data = bytearray() + while True: + event = c.next_event() + print(event) + if event is h11.NEED_DATA: + # Use a small read buffer to make things more challenging + # and exercise more paths :-) + c.receive_data(s.recv(10)) + continue + if type(event) is h11.Response: + assert event.status_code == 200 + if type(event) is h11.Data: + data += event.data + if type(event) is h11.EndOfMessage: + break + assert bytes(data) == test_file_data + + +class H11RequestHandler(socketserver.BaseRequestHandler): + def handle(self) -> None: + with closing(self.request) as s: + c = h11.Connection(h11.SERVER) + request = None + while True: + event = c.next_event() + if event is h11.NEED_DATA: + # Use a small read buffer to make things more challenging + # and exercise more paths :-) + c.receive_data(s.recv(10)) + continue + if type(event) is h11.Request: + request = event + if type(event) is h11.EndOfMessage: + break + assert request is not None + info = json.dumps( + { + "method": request.method.decode("ascii"), + "target": request.target.decode("ascii"), + "headers": { + name.decode("ascii"): value.decode("ascii") + for (name, value) in request.headers + }, + } + ) + s.sendall(c.send(h11.Response(status_code=200, headers=[]))) # type: ignore[arg-type] + s.sendall(c.send(h11.Data(data=info.encode("ascii")))) + s.sendall(c.send(h11.EndOfMessage())) + + +def test_h11_as_server() -> None: + with socket_server(H11RequestHandler) as httpd: + host, port = httpd.server_address + url = "http://{}:{}/some-path".format(host, port) + with closing(urlopen(url)) as f: + assert f.getcode() == 200 + data = f.read() + info = json.loads(data.decode("ascii")) + print(info) + assert info["method"] == "GET" + assert info["target"] == "/some-path" + assert "urllib" in info["headers"]["user-agent"] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_connection.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_connection.py new file mode 100644 index 00000000..73a27b98 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_connection.py @@ -0,0 +1,1122 @@ +from typing import Any, cast, Dict, List, Optional, Tuple, Type + +import pytest + +from .._connection import _body_framing, _keep_alive, Connection, NEED_DATA, PAUSED +from .._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from .._state import ( + CLIENT, + CLOSED, + DONE, + ERROR, + IDLE, + MIGHT_SWITCH_PROTOCOL, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, + SWITCHED_PROTOCOL, +) +from .._util import LocalProtocolError, RemoteProtocolError, Sentinel +from .helpers import ConnectionPair, get_all_events, receive_and_get + + +def test__keep_alive() -> None: + assert _keep_alive( + Request(method="GET", target="/", headers=[("Host", "Example.com")]) + ) + assert not _keep_alive( + Request( + method="GET", + target="/", + headers=[("Host", "Example.com"), ("Connection", "close")], + ) + ) + assert not _keep_alive( + Request( + method="GET", + target="/", + headers=[("Host", "Example.com"), ("Connection", "a, b, cLOse, foo")], + ) + ) + assert not _keep_alive( + Request(method="GET", target="/", headers=[], http_version="1.0") # type: ignore[arg-type] + ) + + assert _keep_alive(Response(status_code=200, headers=[])) # type: ignore[arg-type] + assert not _keep_alive(Response(status_code=200, headers=[("Connection", "close")])) + assert not _keep_alive( + Response(status_code=200, headers=[("Connection", "a, b, cLOse, foo")]) + ) + assert not _keep_alive(Response(status_code=200, headers=[], http_version="1.0")) # type: ignore[arg-type] + + +def test__body_framing() -> None: + def headers(cl: Optional[int], te: bool) -> List[Tuple[str, str]]: + headers = [] + if cl is not None: + headers.append(("Content-Length", str(cl))) + if te: + headers.append(("Transfer-Encoding", "chunked")) + return headers + + def resp( + status_code: int = 200, cl: Optional[int] = None, te: bool = False + ) -> Response: + return Response(status_code=status_code, headers=headers(cl, te)) + + def req(cl: Optional[int] = None, te: bool = False) -> Request: + h = headers(cl, te) + h += [("Host", "example.com")] + return Request(method="GET", target="/", headers=h) + + # Special cases where the headers are ignored: + for kwargs in [{}, {"cl": 100}, {"te": True}, {"cl": 100, "te": True}]: + kwargs = cast(Dict[str, Any], kwargs) + for meth, r in [ + (b"HEAD", resp(**kwargs)), + (b"GET", resp(status_code=204, **kwargs)), + (b"GET", resp(status_code=304, **kwargs)), + ]: + assert _body_framing(meth, r) == ("content-length", (0,)) + + # Transfer-encoding + for kwargs in [{"te": True}, {"cl": 100, "te": True}]: + kwargs = cast(Dict[str, Any], kwargs) + for meth, r in [(None, req(**kwargs)), (b"GET", resp(**kwargs))]: # type: ignore + assert _body_framing(meth, r) == ("chunked", ()) + + # Content-Length + for meth, r in [(None, req(cl=100)), (b"GET", resp(cl=100))]: # type: ignore + assert _body_framing(meth, r) == ("content-length", (100,)) + + # No headers + assert _body_framing(None, req()) == ("content-length", (0,)) # type: ignore + assert _body_framing(b"GET", resp()) == ("http/1.0", ()) + + +def test_Connection_basics_and_content_length() -> None: + with pytest.raises(ValueError): + Connection("CLIENT") # type: ignore + + p = ConnectionPair() + assert p.conn[CLIENT].our_role is CLIENT + assert p.conn[CLIENT].their_role is SERVER + assert p.conn[SERVER].our_role is SERVER + assert p.conn[SERVER].their_role is CLIENT + + data = p.send( + CLIENT, + Request( + method="GET", + target="/", + headers=[("Host", "example.com"), ("Content-Length", "10")], + ), + ) + assert data == ( + b"GET / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 10\r\n\r\n" + ) + + for conn in p.conns: + assert conn.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} + assert p.conn[CLIENT].our_state is SEND_BODY + assert p.conn[CLIENT].their_state is SEND_RESPONSE + assert p.conn[SERVER].our_state is SEND_RESPONSE + assert p.conn[SERVER].their_state is SEND_BODY + + assert p.conn[CLIENT].their_http_version is None + assert p.conn[SERVER].their_http_version == b"1.1" + + data = p.send(SERVER, InformationalResponse(status_code=100, headers=[])) # type: ignore[arg-type] + assert data == b"HTTP/1.1 100 \r\n\r\n" + + data = p.send(SERVER, Response(status_code=200, headers=[("Content-Length", "11")])) + assert data == b"HTTP/1.1 200 \r\nContent-Length: 11\r\n\r\n" + + for conn in p.conns: + assert conn.states == {CLIENT: SEND_BODY, SERVER: SEND_BODY} + + assert p.conn[CLIENT].their_http_version == b"1.1" + assert p.conn[SERVER].their_http_version == b"1.1" + + data = p.send(CLIENT, Data(data=b"12345")) + assert data == b"12345" + data = p.send( + CLIENT, Data(data=b"67890"), expect=[Data(data=b"67890"), EndOfMessage()] + ) + assert data == b"67890" + data = p.send(CLIENT, EndOfMessage(), expect=[]) + assert data == b"" + + for conn in p.conns: + assert conn.states == {CLIENT: DONE, SERVER: SEND_BODY} + + data = p.send(SERVER, Data(data=b"1234567890")) + assert data == b"1234567890" + data = p.send(SERVER, Data(data=b"1"), expect=[Data(data=b"1"), EndOfMessage()]) + assert data == b"1" + data = p.send(SERVER, EndOfMessage(), expect=[]) + assert data == b"" + + for conn in p.conns: + assert conn.states == {CLIENT: DONE, SERVER: DONE} + + +def test_chunked() -> None: + p = ConnectionPair() + + p.send( + CLIENT, + Request( + method="GET", + target="/", + headers=[("Host", "example.com"), ("Transfer-Encoding", "chunked")], + ), + ) + data = p.send(CLIENT, Data(data=b"1234567890", chunk_start=True, chunk_end=True)) + assert data == b"a\r\n1234567890\r\n" + data = p.send(CLIENT, Data(data=b"abcde", chunk_start=True, chunk_end=True)) + assert data == b"5\r\nabcde\r\n" + data = p.send(CLIENT, Data(data=b""), expect=[]) + assert data == b"" + data = p.send(CLIENT, EndOfMessage(headers=[("hello", "there")])) + assert data == b"0\r\nhello: there\r\n\r\n" + + p.send( + SERVER, Response(status_code=200, headers=[("Transfer-Encoding", "chunked")]) + ) + p.send(SERVER, Data(data=b"54321", chunk_start=True, chunk_end=True)) + p.send(SERVER, Data(data=b"12345", chunk_start=True, chunk_end=True)) + p.send(SERVER, EndOfMessage()) + + for conn in p.conns: + assert conn.states == {CLIENT: DONE, SERVER: DONE} + + +def test_chunk_boundaries() -> None: + conn = Connection(our_role=SERVER) + + request = ( + b"POST / HTTP/1.1\r\n" + b"Host: example.com\r\n" + b"Transfer-Encoding: chunked\r\n" + b"\r\n" + ) + conn.receive_data(request) + assert conn.next_event() == Request( + method="POST", + target="/", + headers=[("Host", "example.com"), ("Transfer-Encoding", "chunked")], + ) + assert conn.next_event() is NEED_DATA + + conn.receive_data(b"5\r\nhello\r\n") + assert conn.next_event() == Data(data=b"hello", chunk_start=True, chunk_end=True) + + conn.receive_data(b"5\r\nhel") + assert conn.next_event() == Data(data=b"hel", chunk_start=True, chunk_end=False) + + conn.receive_data(b"l") + assert conn.next_event() == Data(data=b"l", chunk_start=False, chunk_end=False) + + conn.receive_data(b"o\r\n") + assert conn.next_event() == Data(data=b"o", chunk_start=False, chunk_end=True) + + conn.receive_data(b"5\r\nhello") + assert conn.next_event() == Data(data=b"hello", chunk_start=True, chunk_end=True) + + conn.receive_data(b"\r\n") + assert conn.next_event() == NEED_DATA + + conn.receive_data(b"0\r\n\r\n") + assert conn.next_event() == EndOfMessage() + + +def test_client_talking_to_http10_server() -> None: + c = Connection(CLIENT) + c.send(Request(method="GET", target="/", headers=[("Host", "example.com")])) + c.send(EndOfMessage()) + assert c.our_state is DONE + # No content-length, so Http10 framing for body + assert receive_and_get(c, b"HTTP/1.0 200 OK\r\n\r\n") == [ + Response(status_code=200, headers=[], http_version="1.0", reason=b"OK") # type: ignore[arg-type] + ] + assert c.our_state is MUST_CLOSE + assert receive_and_get(c, b"12345") == [Data(data=b"12345")] + assert receive_and_get(c, b"67890") == [Data(data=b"67890")] + assert receive_and_get(c, b"") == [EndOfMessage(), ConnectionClosed()] + assert c.their_state is CLOSED + + +def test_server_talking_to_http10_client() -> None: + c = Connection(SERVER) + # No content-length, so no body + # NB: no host header + assert receive_and_get(c, b"GET / HTTP/1.0\r\n\r\n") == [ + Request(method="GET", target="/", headers=[], http_version="1.0"), # type: ignore[arg-type] + EndOfMessage(), + ] + assert c.their_state is MUST_CLOSE + + # We automatically Connection: close back at them + assert ( + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + == b"HTTP/1.1 200 \r\nConnection: close\r\n\r\n" + ) + + assert c.send(Data(data=b"12345")) == b"12345" + assert c.send(EndOfMessage()) == b"" + assert c.our_state is MUST_CLOSE + + # Check that it works if they do send Content-Length + c = Connection(SERVER) + # NB: no host header + assert receive_and_get(c, b"POST / HTTP/1.0\r\nContent-Length: 10\r\n\r\n1") == [ + Request( + method="POST", + target="/", + headers=[("Content-Length", "10")], + http_version="1.0", + ), + Data(data=b"1"), + ] + assert receive_and_get(c, b"234567890") == [Data(data=b"234567890"), EndOfMessage()] + assert c.their_state is MUST_CLOSE + assert receive_and_get(c, b"") == [ConnectionClosed()] + + +def test_automatic_transfer_encoding_in_response() -> None: + # Check that in responses, the user can specify either Transfer-Encoding: + # chunked or no framing at all, and in both cases we automatically select + # the right option depending on whether the peer speaks HTTP/1.0 or + # HTTP/1.1 + for user_headers in [ + [("Transfer-Encoding", "chunked")], + [], + # In fact, this even works if Content-Length is set, + # because if both are set then Transfer-Encoding wins + [("Transfer-Encoding", "chunked"), ("Content-Length", "100")], + ]: + user_headers = cast(List[Tuple[str, str]], user_headers) + p = ConnectionPair() + p.send( + CLIENT, + [ + Request(method="GET", target="/", headers=[("Host", "example.com")]), + EndOfMessage(), + ], + ) + # When speaking to HTTP/1.1 client, all of the above cases get + # normalized to Transfer-Encoding: chunked + p.send( + SERVER, + Response(status_code=200, headers=user_headers), + expect=Response( + status_code=200, headers=[("Transfer-Encoding", "chunked")] + ), + ) + + # When speaking to HTTP/1.0 client, all of the above cases get + # normalized to no-framing-headers + c = Connection(SERVER) + receive_and_get(c, b"GET / HTTP/1.0\r\n\r\n") + assert ( + c.send(Response(status_code=200, headers=user_headers)) + == b"HTTP/1.1 200 \r\nConnection: close\r\n\r\n" + ) + assert c.send(Data(data=b"12345")) == b"12345" + + +def test_automagic_connection_close_handling() -> None: + p = ConnectionPair() + # If the user explicitly sets Connection: close, then we notice and + # respect it + p.send( + CLIENT, + [ + Request( + method="GET", + target="/", + headers=[("Host", "example.com"), ("Connection", "close")], + ), + EndOfMessage(), + ], + ) + for conn in p.conns: + assert conn.states[CLIENT] is MUST_CLOSE + # And if the client sets it, the server automatically echoes it back + p.send( + SERVER, + # no header here... + [Response(status_code=204, headers=[]), EndOfMessage()], # type: ignore[arg-type] + # ...but oh look, it arrived anyway + expect=[ + Response(status_code=204, headers=[("connection", "close")]), + EndOfMessage(), + ], + ) + for conn in p.conns: + assert conn.states == {CLIENT: MUST_CLOSE, SERVER: MUST_CLOSE} + + +def test_100_continue() -> None: + def setup() -> ConnectionPair: + p = ConnectionPair() + p.send( + CLIENT, + Request( + method="GET", + target="/", + headers=[ + ("Host", "example.com"), + ("Content-Length", "100"), + ("Expect", "100-continue"), + ], + ), + ) + for conn in p.conns: + assert conn.client_is_waiting_for_100_continue + assert not p.conn[CLIENT].they_are_waiting_for_100_continue + assert p.conn[SERVER].they_are_waiting_for_100_continue + return p + + # Disabled by 100 Continue + p = setup() + p.send(SERVER, InformationalResponse(status_code=100, headers=[])) # type: ignore[arg-type] + for conn in p.conns: + assert not conn.client_is_waiting_for_100_continue + assert not conn.they_are_waiting_for_100_continue + + # Disabled by a real response + p = setup() + p.send( + SERVER, Response(status_code=200, headers=[("Transfer-Encoding", "chunked")]) + ) + for conn in p.conns: + assert not conn.client_is_waiting_for_100_continue + assert not conn.they_are_waiting_for_100_continue + + # Disabled by the client going ahead and sending stuff anyway + p = setup() + p.send(CLIENT, Data(data=b"12345")) + for conn in p.conns: + assert not conn.client_is_waiting_for_100_continue + assert not conn.they_are_waiting_for_100_continue + + +def test_max_incomplete_event_size_countermeasure() -> None: + # Infinitely long headers are definitely not okay + c = Connection(SERVER) + c.receive_data(b"GET / HTTP/1.0\r\nEndless: ") + assert c.next_event() is NEED_DATA + with pytest.raises(RemoteProtocolError): + while True: + c.receive_data(b"a" * 1024) + c.next_event() + + # Checking that the same header is accepted / rejected depending on the + # max_incomplete_event_size setting: + c = Connection(SERVER, max_incomplete_event_size=5000) + c.receive_data(b"GET / HTTP/1.0\r\nBig: ") + c.receive_data(b"a" * 4000) + c.receive_data(b"\r\n\r\n") + assert get_all_events(c) == [ + Request( + method="GET", target="/", http_version="1.0", headers=[("big", "a" * 4000)] + ), + EndOfMessage(), + ] + + c = Connection(SERVER, max_incomplete_event_size=4000) + c.receive_data(b"GET / HTTP/1.0\r\nBig: ") + c.receive_data(b"a" * 4000) + with pytest.raises(RemoteProtocolError): + c.next_event() + + # Temporarily exceeding the size limit is fine, as long as its done with + # complete events: + c = Connection(SERVER, max_incomplete_event_size=5000) + c.receive_data(b"GET / HTTP/1.0\r\nContent-Length: 10000") + c.receive_data(b"\r\n\r\n" + b"a" * 10000) + assert get_all_events(c) == [ + Request( + method="GET", + target="/", + http_version="1.0", + headers=[("Content-Length", "10000")], + ), + Data(data=b"a" * 10000), + EndOfMessage(), + ] + + c = Connection(SERVER, max_incomplete_event_size=100) + # Two pipelined requests to create a way-too-big receive buffer... but + # it's fine because we're not checking + c.receive_data( + b"GET /1 HTTP/1.1\r\nHost: a\r\n\r\n" + b"GET /2 HTTP/1.1\r\nHost: b\r\n\r\n" + b"X" * 1000 + ) + assert get_all_events(c) == [ + Request(method="GET", target="/1", headers=[("host", "a")]), + EndOfMessage(), + ] + # Even more data comes in, still no problem + c.receive_data(b"X" * 1000) + # We can respond and reuse to get the second pipelined request + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + c.send(EndOfMessage()) + c.start_next_cycle() + assert get_all_events(c) == [ + Request(method="GET", target="/2", headers=[("host", "b")]), + EndOfMessage(), + ] + # But once we unpause and try to read the next message, and find that it's + # incomplete and the buffer is *still* way too large, then *that's* a + # problem: + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + c.send(EndOfMessage()) + c.start_next_cycle() + with pytest.raises(RemoteProtocolError): + c.next_event() + + +def test_reuse_simple() -> None: + p = ConnectionPair() + p.send( + CLIENT, + [Request(method="GET", target="/", headers=[("Host", "a")]), EndOfMessage()], + ) + p.send( + SERVER, + [ + Response(status_code=200, headers=[(b"transfer-encoding", b"chunked")]), + EndOfMessage(), + ], + ) + for conn in p.conns: + assert conn.states == {CLIENT: DONE, SERVER: DONE} + conn.start_next_cycle() + + p.send( + CLIENT, + [ + Request(method="DELETE", target="/foo", headers=[("Host", "a")]), + EndOfMessage(), + ], + ) + p.send( + SERVER, + [ + Response(status_code=404, headers=[(b"transfer-encoding", b"chunked")]), + EndOfMessage(), + ], + ) + + +def test_pipelining() -> None: + # Client doesn't support pipelining, so we have to do this by hand + c = Connection(SERVER) + assert c.next_event() is NEED_DATA + # 3 requests all bunched up + c.receive_data( + b"GET /1 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" + b"12345" + b"GET /2 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" + b"67890" + b"GET /3 HTTP/1.1\r\nHost: a.com\r\n\r\n" + ) + assert get_all_events(c) == [ + Request( + method="GET", + target="/1", + headers=[("Host", "a.com"), ("Content-Length", "5")], + ), + Data(data=b"12345"), + EndOfMessage(), + ] + assert c.their_state is DONE + assert c.our_state is SEND_RESPONSE + + assert c.next_event() is PAUSED + + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + c.send(EndOfMessage()) + assert c.their_state is DONE + assert c.our_state is DONE + + c.start_next_cycle() + + assert get_all_events(c) == [ + Request( + method="GET", + target="/2", + headers=[("Host", "a.com"), ("Content-Length", "5")], + ), + Data(data=b"67890"), + EndOfMessage(), + ] + assert c.next_event() is PAUSED + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + c.send(EndOfMessage()) + c.start_next_cycle() + + assert get_all_events(c) == [ + Request(method="GET", target="/3", headers=[("Host", "a.com")]), + EndOfMessage(), + ] + # Doesn't pause this time, no trailing data + assert c.next_event() is NEED_DATA + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + c.send(EndOfMessage()) + + # Arrival of more data triggers pause + assert c.next_event() is NEED_DATA + c.receive_data(b"SADF") + assert c.next_event() is PAUSED + assert c.trailing_data == (b"SADF", False) + # If EOF arrives while paused, we don't see that either: + c.receive_data(b"") + assert c.trailing_data == (b"SADF", True) + assert c.next_event() is PAUSED + c.receive_data(b"") + assert c.next_event() is PAUSED + # Can't call receive_data with non-empty buf after closing it + with pytest.raises(RuntimeError): + c.receive_data(b"FDSA") + + +def test_protocol_switch() -> None: + for (req, deny, accept) in [ + ( + Request( + method="CONNECT", + target="example.com:443", + headers=[("Host", "foo"), ("Content-Length", "1")], + ), + Response(status_code=404, headers=[(b"transfer-encoding", b"chunked")]), + Response(status_code=200, headers=[(b"transfer-encoding", b"chunked")]), + ), + ( + Request( + method="GET", + target="/", + headers=[("Host", "foo"), ("Content-Length", "1"), ("Upgrade", "a, b")], + ), + Response(status_code=200, headers=[(b"transfer-encoding", b"chunked")]), + InformationalResponse(status_code=101, headers=[("Upgrade", "a")]), + ), + ( + Request( + method="CONNECT", + target="example.com:443", + headers=[("Host", "foo"), ("Content-Length", "1"), ("Upgrade", "a, b")], + ), + Response(status_code=404, headers=[(b"transfer-encoding", b"chunked")]), + # Accept CONNECT, not upgrade + Response(status_code=200, headers=[(b"transfer-encoding", b"chunked")]), + ), + ( + Request( + method="CONNECT", + target="example.com:443", + headers=[("Host", "foo"), ("Content-Length", "1"), ("Upgrade", "a, b")], + ), + Response(status_code=404, headers=[(b"transfer-encoding", b"chunked")]), + # Accept Upgrade, not CONNECT + InformationalResponse(status_code=101, headers=[("Upgrade", "b")]), + ), + ]: + + def setup() -> ConnectionPair: + p = ConnectionPair() + p.send(CLIENT, req) + # No switch-related state change stuff yet; the client has to + # finish the request before that kicks in + for conn in p.conns: + assert conn.states[CLIENT] is SEND_BODY + p.send(CLIENT, [Data(data=b"1"), EndOfMessage()]) + for conn in p.conns: + assert conn.states[CLIENT] is MIGHT_SWITCH_PROTOCOL + assert p.conn[SERVER].next_event() is PAUSED + return p + + # Test deny case + p = setup() + p.send(SERVER, deny) + for conn in p.conns: + assert conn.states == {CLIENT: DONE, SERVER: SEND_BODY} + p.send(SERVER, EndOfMessage()) + # Check that re-use is still allowed after a denial + for conn in p.conns: + conn.start_next_cycle() + + # Test accept case + p = setup() + p.send(SERVER, accept) + for conn in p.conns: + assert conn.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} + conn.receive_data(b"123") + assert conn.next_event() is PAUSED + conn.receive_data(b"456") + assert conn.next_event() is PAUSED + assert conn.trailing_data == (b"123456", False) + + # Pausing in might-switch, then recovery + # (weird artificial case where the trailing data actually is valid + # HTTP for some reason, because this makes it easier to test the state + # logic) + p = setup() + sc = p.conn[SERVER] + sc.receive_data(b"GET / HTTP/1.0\r\n\r\n") + assert sc.next_event() is PAUSED + assert sc.trailing_data == (b"GET / HTTP/1.0\r\n\r\n", False) + sc.send(deny) + assert sc.next_event() is PAUSED + sc.send(EndOfMessage()) + sc.start_next_cycle() + assert get_all_events(sc) == [ + Request(method="GET", target="/", headers=[], http_version="1.0"), # type: ignore[arg-type] + EndOfMessage(), + ] + + # When we're DONE, have no trailing data, and the connection gets + # closed, we report ConnectionClosed(). When we're in might-switch or + # switched, we don't. + p = setup() + sc = p.conn[SERVER] + sc.receive_data(b"") + assert sc.next_event() is PAUSED + assert sc.trailing_data == (b"", True) + p.send(SERVER, accept) + assert sc.next_event() is PAUSED + + p = setup() + sc = p.conn[SERVER] + sc.receive_data(b"") + assert sc.next_event() is PAUSED + sc.send(deny) + assert sc.next_event() == ConnectionClosed() + + # You can't send after switching protocols, or while waiting for a + # protocol switch + p = setup() + with pytest.raises(LocalProtocolError): + p.conn[CLIENT].send( + Request(method="GET", target="/", headers=[("Host", "a")]) + ) + p = setup() + p.send(SERVER, accept) + with pytest.raises(LocalProtocolError): + p.conn[SERVER].send(Data(data=b"123")) + + +def test_close_simple() -> None: + # Just immediately closing a new connection without anything having + # happened yet. + for (who_shot_first, who_shot_second) in [(CLIENT, SERVER), (SERVER, CLIENT)]: + + def setup() -> ConnectionPair: + p = ConnectionPair() + p.send(who_shot_first, ConnectionClosed()) + for conn in p.conns: + assert conn.states == { + who_shot_first: CLOSED, + who_shot_second: MUST_CLOSE, + } + return p + + # You can keep putting b"" into a closed connection, and you keep + # getting ConnectionClosed() out: + p = setup() + assert p.conn[who_shot_second].next_event() == ConnectionClosed() + assert p.conn[who_shot_second].next_event() == ConnectionClosed() + p.conn[who_shot_second].receive_data(b"") + assert p.conn[who_shot_second].next_event() == ConnectionClosed() + # Second party can close... + p = setup() + p.send(who_shot_second, ConnectionClosed()) + for conn in p.conns: + assert conn.our_state is CLOSED + assert conn.their_state is CLOSED + # But trying to receive new data on a closed connection is a + # RuntimeError (not ProtocolError, because the problem here isn't + # violation of HTTP, it's violation of physics) + p = setup() + with pytest.raises(RuntimeError): + p.conn[who_shot_second].receive_data(b"123") + # And receiving new data on a MUST_CLOSE connection is a ProtocolError + p = setup() + p.conn[who_shot_first].receive_data(b"GET") + with pytest.raises(RemoteProtocolError): + p.conn[who_shot_first].next_event() + + +def test_close_different_states() -> None: + req = [ + Request(method="GET", target="/foo", headers=[("Host", "a")]), + EndOfMessage(), + ] + resp = [ + Response(status_code=200, headers=[(b"transfer-encoding", b"chunked")]), + EndOfMessage(), + ] + + # Client before request + p = ConnectionPair() + p.send(CLIENT, ConnectionClosed()) + for conn in p.conns: + assert conn.states == {CLIENT: CLOSED, SERVER: MUST_CLOSE} + + # Client after request + p = ConnectionPair() + p.send(CLIENT, req) + p.send(CLIENT, ConnectionClosed()) + for conn in p.conns: + assert conn.states == {CLIENT: CLOSED, SERVER: SEND_RESPONSE} + + # Server after request -> not allowed + p = ConnectionPair() + p.send(CLIENT, req) + with pytest.raises(LocalProtocolError): + p.conn[SERVER].send(ConnectionClosed()) + p.conn[CLIENT].receive_data(b"") + with pytest.raises(RemoteProtocolError): + p.conn[CLIENT].next_event() + + # Server after response + p = ConnectionPair() + p.send(CLIENT, req) + p.send(SERVER, resp) + p.send(SERVER, ConnectionClosed()) + for conn in p.conns: + assert conn.states == {CLIENT: MUST_CLOSE, SERVER: CLOSED} + + # Both after closing (ConnectionClosed() is idempotent) + p = ConnectionPair() + p.send(CLIENT, req) + p.send(SERVER, resp) + p.send(CLIENT, ConnectionClosed()) + p.send(SERVER, ConnectionClosed()) + p.send(CLIENT, ConnectionClosed()) + p.send(SERVER, ConnectionClosed()) + + # In the middle of sending -> not allowed + p = ConnectionPair() + p.send( + CLIENT, + Request( + method="GET", target="/", headers=[("Host", "a"), ("Content-Length", "10")] + ), + ) + with pytest.raises(LocalProtocolError): + p.conn[CLIENT].send(ConnectionClosed()) + p.conn[SERVER].receive_data(b"") + with pytest.raises(RemoteProtocolError): + p.conn[SERVER].next_event() + + +# Receive several requests and then client shuts down their side of the +# connection; we can respond to each +def test_pipelined_close() -> None: + c = Connection(SERVER) + # 2 requests then a close + c.receive_data( + b"GET /1 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" + b"12345" + b"GET /2 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" + b"67890" + ) + c.receive_data(b"") + assert get_all_events(c) == [ + Request( + method="GET", + target="/1", + headers=[("host", "a.com"), ("content-length", "5")], + ), + Data(data=b"12345"), + EndOfMessage(), + ] + assert c.states[CLIENT] is DONE + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + c.send(EndOfMessage()) + assert c.states[SERVER] is DONE + c.start_next_cycle() + assert get_all_events(c) == [ + Request( + method="GET", + target="/2", + headers=[("host", "a.com"), ("content-length", "5")], + ), + Data(data=b"67890"), + EndOfMessage(), + ConnectionClosed(), + ] + assert c.states == {CLIENT: CLOSED, SERVER: SEND_RESPONSE} + c.send(Response(status_code=200, headers=[])) # type: ignore[arg-type] + c.send(EndOfMessage()) + assert c.states == {CLIENT: CLOSED, SERVER: MUST_CLOSE} + c.send(ConnectionClosed()) + assert c.states == {CLIENT: CLOSED, SERVER: CLOSED} + + +def test_sendfile() -> None: + class SendfilePlaceholder: + def __len__(self) -> int: + return 10 + + placeholder = SendfilePlaceholder() + + def setup( + header: Tuple[str, str], http_version: str + ) -> Tuple[Connection, Optional[List[bytes]]]: + c = Connection(SERVER) + receive_and_get( + c, "GET / HTTP/{}\r\nHost: a\r\n\r\n".format(http_version).encode("ascii") + ) + headers = [] + if header: + headers.append(header) + c.send(Response(status_code=200, headers=headers)) + return c, c.send_with_data_passthrough(Data(data=placeholder)) # type: ignore + + c, data = setup(("Content-Length", "10"), "1.1") + assert data == [placeholder] # type: ignore + # Raises an error if the connection object doesn't think we've sent + # exactly 10 bytes + c.send(EndOfMessage()) + + _, data = setup(("Transfer-Encoding", "chunked"), "1.1") + assert placeholder in data # type: ignore + data[data.index(placeholder)] = b"x" * 10 # type: ignore + assert b"".join(data) == b"a\r\nxxxxxxxxxx\r\n" # type: ignore + + c, data = setup(None, "1.0") # type: ignore + assert data == [placeholder] # type: ignore + assert c.our_state is SEND_BODY + + +def test_errors() -> None: + # After a receive error, you can't receive + for role in [CLIENT, SERVER]: + c = Connection(our_role=role) + c.receive_data(b"gibberish\r\n\r\n") + with pytest.raises(RemoteProtocolError): + c.next_event() + # Now any attempt to receive continues to raise + assert c.their_state is ERROR + assert c.our_state is not ERROR + print(c._cstate.states) + with pytest.raises(RemoteProtocolError): + c.next_event() + # But we can still yell at the client for sending us gibberish + if role is SERVER: + assert ( + c.send(Response(status_code=400, headers=[])) # type: ignore[arg-type] + == b"HTTP/1.1 400 \r\nConnection: close\r\n\r\n" + ) + + # After an error sending, you can no longer send + # (This is especially important for things like content-length errors, + # where there's complex internal state being modified) + def conn(role: Type[Sentinel]) -> Connection: + c = Connection(our_role=role) + if role is SERVER: + # Put it into the state where it *could* send a response... + receive_and_get(c, b"GET / HTTP/1.0\r\n\r\n") + assert c.our_state is SEND_RESPONSE + return c + + for role in [CLIENT, SERVER]: + if role is CLIENT: + # This HTTP/1.0 request won't be detected as bad until after we go + # through the state machine and hit the writing code + good = Request(method="GET", target="/", headers=[("Host", "example.com")]) + bad = Request( + method="GET", + target="/", + headers=[("Host", "example.com")], + http_version="1.0", + ) + elif role is SERVER: + good = Response(status_code=200, headers=[]) # type: ignore[arg-type,assignment] + bad = Response(status_code=200, headers=[], http_version="1.0") # type: ignore[arg-type,assignment] + # Make sure 'good' actually is good + c = conn(role) + c.send(good) + assert c.our_state is not ERROR + # Do that again, but this time sending 'bad' first + c = conn(role) + with pytest.raises(LocalProtocolError): + c.send(bad) + assert c.our_state is ERROR + assert c.their_state is not ERROR + # Now 'good' is not so good + with pytest.raises(LocalProtocolError): + c.send(good) + + # And check send_failed() too + c = conn(role) + c.send_failed() + assert c.our_state is ERROR + assert c.their_state is not ERROR + # This is idempotent + c.send_failed() + assert c.our_state is ERROR + assert c.their_state is not ERROR + + +def test_idle_receive_nothing() -> None: + # At one point this incorrectly raised an error + for role in [CLIENT, SERVER]: + c = Connection(role) + assert c.next_event() is NEED_DATA + + +def test_connection_drop() -> None: + c = Connection(SERVER) + c.receive_data(b"GET /") + assert c.next_event() is NEED_DATA + c.receive_data(b"") + with pytest.raises(RemoteProtocolError): + c.next_event() + + +def test_408_request_timeout() -> None: + # Should be able to send this spontaneously as a server without seeing + # anything from client + p = ConnectionPair() + p.send(SERVER, Response(status_code=408, headers=[(b"connection", b"close")])) + + +# This used to raise IndexError +def test_empty_request() -> None: + c = Connection(SERVER) + c.receive_data(b"\r\n") + with pytest.raises(RemoteProtocolError): + c.next_event() + + +# This used to raise IndexError +def test_empty_response() -> None: + c = Connection(CLIENT) + c.send(Request(method="GET", target="/", headers=[("Host", "a")])) + c.receive_data(b"\r\n") + with pytest.raises(RemoteProtocolError): + c.next_event() + + +@pytest.mark.parametrize( + "data", + [ + b"\x00", + b"\x20", + b"\x16\x03\x01\x00\xa5", # Typical start of a TLS Client Hello + ], +) +def test_early_detection_of_invalid_request(data: bytes) -> None: + c = Connection(SERVER) + # Early detection should occur before even receiving a `\r\n` + c.receive_data(data) + with pytest.raises(RemoteProtocolError): + c.next_event() + + +@pytest.mark.parametrize( + "data", + [ + b"\x00", + b"\x20", + b"\x16\x03\x03\x00\x31", # Typical start of a TLS Server Hello + ], +) +def test_early_detection_of_invalid_response(data: bytes) -> None: + c = Connection(CLIENT) + # Early detection should occur before even receiving a `\r\n` + c.receive_data(data) + with pytest.raises(RemoteProtocolError): + c.next_event() + + +# This used to give different headers for HEAD and GET. +# The correct way to handle HEAD is to put whatever headers we *would* have +# put if it were a GET -- even though we know that for HEAD, those headers +# will be ignored. +def test_HEAD_framing_headers() -> None: + def setup(method: bytes, http_version: bytes) -> Connection: + c = Connection(SERVER) + c.receive_data( + method + b" / HTTP/" + http_version + b"\r\n" + b"Host: example.com\r\n\r\n" + ) + assert type(c.next_event()) is Request + assert type(c.next_event()) is EndOfMessage + return c + + for method in [b"GET", b"HEAD"]: + # No Content-Length, HTTP/1.1 peer, should use chunked + c = setup(method, b"1.1") + assert ( + c.send(Response(status_code=200, headers=[])) == b"HTTP/1.1 200 \r\n" # type: ignore[arg-type] + b"Transfer-Encoding: chunked\r\n\r\n" + ) + + # No Content-Length, HTTP/1.0 peer, frame with connection: close + c = setup(method, b"1.0") + assert ( + c.send(Response(status_code=200, headers=[])) == b"HTTP/1.1 200 \r\n" # type: ignore[arg-type] + b"Connection: close\r\n\r\n" + ) + + # Content-Length + Transfer-Encoding, TE wins + c = setup(method, b"1.1") + assert ( + c.send( + Response( + status_code=200, + headers=[ + ("Content-Length", "100"), + ("Transfer-Encoding", "chunked"), + ], + ) + ) + == b"HTTP/1.1 200 \r\n" + b"Transfer-Encoding: chunked\r\n\r\n" + ) + + +def test_special_exceptions_for_lost_connection_in_message_body() -> None: + c = Connection(SERVER) + c.receive_data( + b"POST / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 100\r\n\r\n" + ) + assert type(c.next_event()) is Request + assert c.next_event() is NEED_DATA + c.receive_data(b"12345") + assert c.next_event() == Data(data=b"12345") + c.receive_data(b"") + with pytest.raises(RemoteProtocolError) as excinfo: + c.next_event() + assert "received 5 bytes" in str(excinfo.value) + assert "expected 100" in str(excinfo.value) + + c = Connection(SERVER) + c.receive_data( + b"POST / HTTP/1.1\r\n" + b"Host: example.com\r\n" + b"Transfer-Encoding: chunked\r\n\r\n" + ) + assert type(c.next_event()) is Request + assert c.next_event() is NEED_DATA + c.receive_data(b"8\r\n012345") + assert c.next_event().data == b"012345" # type: ignore + c.receive_data(b"") + with pytest.raises(RemoteProtocolError) as excinfo: + c.next_event() + assert "incomplete chunked read" in str(excinfo.value) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_events.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_events.py new file mode 100644 index 00000000..bc6c3137 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_events.py @@ -0,0 +1,150 @@ +from http import HTTPStatus + +import pytest + +from .. import _events +from .._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from .._util import LocalProtocolError + + +def test_events() -> None: + with pytest.raises(LocalProtocolError): + # Missing Host: + req = Request( + method="GET", target="/", headers=[("a", "b")], http_version="1.1" + ) + # But this is okay (HTTP/1.0) + req = Request(method="GET", target="/", headers=[("a", "b")], http_version="1.0") + # fields are normalized + assert req.method == b"GET" + assert req.target == b"/" + assert req.headers == [(b"a", b"b")] + assert req.http_version == b"1.0" + + # This is also okay -- has a Host (with weird capitalization, which is ok) + req = Request( + method="GET", + target="/", + headers=[("a", "b"), ("hOSt", "example.com")], + http_version="1.1", + ) + # we normalize header capitalization + assert req.headers == [(b"a", b"b"), (b"host", b"example.com")] + + # Multiple host is bad too + with pytest.raises(LocalProtocolError): + req = Request( + method="GET", + target="/", + headers=[("Host", "a"), ("Host", "a")], + http_version="1.1", + ) + # Even for HTTP/1.0 + with pytest.raises(LocalProtocolError): + req = Request( + method="GET", + target="/", + headers=[("Host", "a"), ("Host", "a")], + http_version="1.0", + ) + + # Header values are validated + for bad_char in "\x00\r\n\f\v": + with pytest.raises(LocalProtocolError): + req = Request( + method="GET", + target="/", + headers=[("Host", "a"), ("Foo", "asd" + bad_char)], + http_version="1.0", + ) + + # But for compatibility we allow non-whitespace control characters, even + # though they're forbidden by the spec. + Request( + method="GET", + target="/", + headers=[("Host", "a"), ("Foo", "asd\x01\x02\x7f")], + http_version="1.0", + ) + + # Request target is validated + for bad_byte in b"\x00\x20\x7f\xee": + target = bytearray(b"/") + target.append(bad_byte) + with pytest.raises(LocalProtocolError): + Request( + method="GET", target=target, headers=[("Host", "a")], http_version="1.1" + ) + + # Request method is validated + with pytest.raises(LocalProtocolError): + Request( + method="GET / HTTP/1.1", + target=target, + headers=[("Host", "a")], + http_version="1.1", + ) + + ir = InformationalResponse(status_code=100, headers=[("Host", "a")]) + assert ir.status_code == 100 + assert ir.headers == [(b"host", b"a")] + assert ir.http_version == b"1.1" + + with pytest.raises(LocalProtocolError): + InformationalResponse(status_code=200, headers=[("Host", "a")]) + + resp = Response(status_code=204, headers=[], http_version="1.0") # type: ignore[arg-type] + assert resp.status_code == 204 + assert resp.headers == [] + assert resp.http_version == b"1.0" + + with pytest.raises(LocalProtocolError): + resp = Response(status_code=100, headers=[], http_version="1.0") # type: ignore[arg-type] + + with pytest.raises(LocalProtocolError): + Response(status_code="100", headers=[], http_version="1.0") # type: ignore[arg-type] + + with pytest.raises(LocalProtocolError): + InformationalResponse(status_code=b"100", headers=[], http_version="1.0") # type: ignore[arg-type] + + d = Data(data=b"asdf") + assert d.data == b"asdf" + + eom = EndOfMessage() + assert eom.headers == [] + + cc = ConnectionClosed() + assert repr(cc) == "ConnectionClosed()" + + +def test_intenum_status_code() -> None: + # https://github.com/python-hyper/h11/issues/72 + + r = Response(status_code=HTTPStatus.OK, headers=[], http_version="1.0") # type: ignore[arg-type] + assert r.status_code == HTTPStatus.OK + assert type(r.status_code) is not type(HTTPStatus.OK) + assert type(r.status_code) is int + + +def test_header_casing() -> None: + r = Request( + method="GET", + target="/", + headers=[("Host", "example.org"), ("Connection", "keep-alive")], + http_version="1.1", + ) + assert len(r.headers) == 2 + assert r.headers[0] == (b"host", b"example.org") + 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"), + ] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_headers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_headers.py new file mode 100644 index 00000000..ba53d088 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_headers.py @@ -0,0 +1,157 @@ +import pytest + +from .._events import Request +from .._headers import ( + get_comma_header, + has_expect_100_continue, + Headers, + normalize_and_validate, + set_comma_header, +) +from .._util import LocalProtocolError + + +def test_normalize_and_validate() -> None: + assert normalize_and_validate([("foo", "bar")]) == [(b"foo", b"bar")] + assert normalize_and_validate([(b"foo", b"bar")]) == [(b"foo", b"bar")] + + # no leading/trailing whitespace in names + with pytest.raises(LocalProtocolError): + normalize_and_validate([(b"foo ", "bar")]) + with pytest.raises(LocalProtocolError): + normalize_and_validate([(b" foo", "bar")]) + + # no weird characters in names + with pytest.raises(LocalProtocolError) as excinfo: + normalize_and_validate([(b"foo bar", b"baz")]) + assert "foo bar" in str(excinfo.value) + with pytest.raises(LocalProtocolError): + normalize_and_validate([(b"foo\x00bar", b"baz")]) + # Not even 8-bit characters: + with pytest.raises(LocalProtocolError): + normalize_and_validate([(b"foo\xffbar", b"baz")]) + # And not even the control characters we allow in values: + with pytest.raises(LocalProtocolError): + normalize_and_validate([(b"foo\x01bar", b"baz")]) + + # no return or NUL characters in values + with pytest.raises(LocalProtocolError) as excinfo: + normalize_and_validate([("foo", "bar\rbaz")]) + assert "bar\\rbaz" in str(excinfo.value) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("foo", "bar\nbaz")]) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("foo", "bar\x00baz")]) + # no leading/trailing whitespace + with pytest.raises(LocalProtocolError): + normalize_and_validate([("foo", "barbaz ")]) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("foo", " barbaz")]) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("foo", "barbaz\t")]) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("foo", "\tbarbaz")]) + + # content-length + assert normalize_and_validate([("Content-Length", "1")]) == [ + (b"content-length", b"1") + ] + with pytest.raises(LocalProtocolError): + normalize_and_validate([("Content-Length", "asdf")]) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("Content-Length", "1x")]) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("Content-Length", "1"), ("Content-Length", "2")]) + assert normalize_and_validate( + [("Content-Length", "0"), ("Content-Length", "0")] + ) == [(b"content-length", b"0")] + assert normalize_and_validate([("Content-Length", "0 , 0")]) == [ + (b"content-length", b"0") + ] + with pytest.raises(LocalProtocolError): + normalize_and_validate( + [("Content-Length", "1"), ("Content-Length", "1"), ("Content-Length", "2")] + ) + with pytest.raises(LocalProtocolError): + normalize_and_validate([("Content-Length", "1 , 1,2")]) + + # transfer-encoding + assert normalize_and_validate([("Transfer-Encoding", "chunked")]) == [ + (b"transfer-encoding", b"chunked") + ] + assert normalize_and_validate([("Transfer-Encoding", "cHuNkEd")]) == [ + (b"transfer-encoding", b"chunked") + ] + with pytest.raises(LocalProtocolError) as excinfo: + normalize_and_validate([("Transfer-Encoding", "gzip")]) + assert excinfo.value.error_status_hint == 501 # Not Implemented + with pytest.raises(LocalProtocolError) as excinfo: + normalize_and_validate( + [("Transfer-Encoding", "chunked"), ("Transfer-Encoding", "gzip")] + ) + assert excinfo.value.error_status_hint == 501 # Not Implemented + + +def test_get_set_comma_header() -> None: + headers = normalize_and_validate( + [ + ("Connection", "close"), + ("whatever", "something"), + ("connectiON", "fOo,, , BAR"), + ] + ) + + assert get_comma_header(headers, b"connection") == [b"close", b"foo", b"bar"] + + headers = set_comma_header(headers, b"newthing", ["a", "b"]) # type: ignore + + with pytest.raises(LocalProtocolError): + set_comma_header(headers, b"newthing", [" a", "b"]) # type: ignore + + assert headers == [ + (b"connection", b"close"), + (b"whatever", b"something"), + (b"connection", b"fOo,, , BAR"), + (b"newthing", b"a"), + (b"newthing", b"b"), + ] + + headers = set_comma_header(headers, b"whatever", ["different thing"]) # type: ignore + + assert headers == [ + (b"connection", b"close"), + (b"connection", b"fOo,, , BAR"), + (b"newthing", b"a"), + (b"newthing", b"b"), + (b"whatever", b"different thing"), + ] + + +def test_has_100_continue() -> None: + assert has_expect_100_continue( + Request( + method="GET", + target="/", + headers=[("Host", "example.com"), ("Expect", "100-continue")], + ) + ) + assert not has_expect_100_continue( + Request(method="GET", target="/", headers=[("Host", "example.com")]) + ) + # Case insensitive + assert has_expect_100_continue( + Request( + method="GET", + target="/", + headers=[("Host", "example.com"), ("Expect", "100-Continue")], + ) + ) + # Doesn't work in HTTP/1.0 + assert not has_expect_100_continue( + Request( + method="GET", + target="/", + headers=[("Host", "example.com"), ("Expect", "100-continue")], + http_version="1.0", + ) + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_helpers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_helpers.py new file mode 100644 index 00000000..c329c767 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_helpers.py @@ -0,0 +1,32 @@ +from .._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from .helpers import normalize_data_events + + +def test_normalize_data_events() -> None: + assert normalize_data_events( + [ + Data(data=bytearray(b"1")), + Data(data=b"2"), + Response(status_code=200, headers=[]), # type: ignore[arg-type] + Data(data=b"3"), + Data(data=b"4"), + EndOfMessage(), + Data(data=b"5"), + Data(data=b"6"), + Data(data=b"7"), + ] + ) == [ + Data(data=b"12"), + Response(status_code=200, headers=[]), # type: ignore[arg-type] + Data(data=b"34"), + EndOfMessage(), + Data(data=b"567"), + ] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_io.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_io.py new file mode 100644 index 00000000..e9c01bd5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_io.py @@ -0,0 +1,566 @@ +from typing import Any, Callable, Generator, List + +import pytest + +from .._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from .._headers import Headers, normalize_and_validate +from .._readers import ( + _obsolete_line_fold, + ChunkedReader, + ContentLengthReader, + Http10Reader, + READERS, +) +from .._receivebuffer import ReceiveBuffer +from .._state import ( + CLIENT, + CLOSED, + DONE, + IDLE, + MIGHT_SWITCH_PROTOCOL, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, + SWITCHED_PROTOCOL, +) +from .._util import LocalProtocolError +from .._writers import ( + ChunkedWriter, + ContentLengthWriter, + Http10Writer, + write_any_response, + write_headers, + write_request, + WRITERS, +) +from .helpers import normalize_data_events + +SIMPLE_CASES = [ + ( + (CLIENT, IDLE), + Request( + method="GET", + target="/a", + headers=[("Host", "foo"), ("Connection", "close")], + ), + b"GET /a HTTP/1.1\r\nHost: foo\r\nConnection: close\r\n\r\n", + ), + ( + (SERVER, SEND_RESPONSE), + Response(status_code=200, headers=[("Connection", "close")], reason=b"OK"), + b"HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", + ), + ( + (SERVER, SEND_RESPONSE), + Response(status_code=200, headers=[], reason=b"OK"), # type: ignore[arg-type] + b"HTTP/1.1 200 OK\r\n\r\n", + ), + ( + (SERVER, SEND_RESPONSE), + InformationalResponse( + status_code=101, headers=[("Upgrade", "websocket")], reason=b"Upgrade" + ), + b"HTTP/1.1 101 Upgrade\r\nUpgrade: websocket\r\n\r\n", + ), + ( + (SERVER, SEND_RESPONSE), + InformationalResponse(status_code=101, headers=[], reason=b"Upgrade"), # type: ignore[arg-type] + b"HTTP/1.1 101 Upgrade\r\n\r\n", + ), +] + + +def dowrite(writer: Callable[..., None], obj: Any) -> bytes: + got_list: List[bytes] = [] + writer(obj, got_list.append) + return b"".join(got_list) + + +def tw(writer: Any, obj: Any, expected: Any) -> None: + got = dowrite(writer, obj) + assert got == expected + + +def makebuf(data: bytes) -> ReceiveBuffer: + buf = ReceiveBuffer() + buf += data + return buf + + +def tr(reader: Any, data: bytes, expected: Any) -> None: + def check(got: Any) -> None: + assert got == expected + # Headers should always be returned as bytes, not e.g. bytearray + # https://github.com/python-hyper/wsproto/pull/54#issuecomment-377709478 + for name, value in getattr(got, "headers", []): + assert type(name) is bytes + assert type(value) is bytes + + # Simple: consume whole thing + buf = makebuf(data) + check(reader(buf)) + assert not buf + + # Incrementally growing buffer + buf = ReceiveBuffer() + for i in range(len(data)): + assert reader(buf) is None + buf += data[i : i + 1] + check(reader(buf)) + + # Trailing data + buf = makebuf(data) + buf += b"trailing" + check(reader(buf)) + assert bytes(buf) == b"trailing" + + +def test_writers_simple() -> None: + for ((role, state), event, binary) in SIMPLE_CASES: + tw(WRITERS[role, state], event, binary) + + +def test_readers_simple() -> None: + for ((role, state), event, binary) in SIMPLE_CASES: + tr(READERS[role, state], binary, event) + + +def test_writers_unusual() -> None: + # Simple test of the write_headers utility routine + tw( + write_headers, + normalize_and_validate([("foo", "bar"), ("baz", "quux")]), + b"foo: bar\r\nbaz: quux\r\n\r\n", + ) + tw(write_headers, Headers([]), b"\r\n") + + # We understand HTTP/1.0, but we don't speak it + with pytest.raises(LocalProtocolError): + tw( + write_request, + Request( + method="GET", + target="/", + headers=[("Host", "foo"), ("Connection", "close")], + http_version="1.0", + ), + None, + ) + with pytest.raises(LocalProtocolError): + tw( + write_any_response, + Response( + status_code=200, headers=[("Connection", "close")], http_version="1.0" + ), + None, + ) + + +def test_readers_unusual() -> None: + # Reading HTTP/1.0 + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.0\r\nSome: header\r\n\r\n", + Request( + method="HEAD", + target="/foo", + headers=[("Some", "header")], + http_version="1.0", + ), + ) + + # check no-headers, since it's only legal with HTTP/1.0 + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.0\r\n\r\n", + Request(method="HEAD", target="/foo", headers=[], http_version="1.0"), # type: ignore[arg-type] + ) + + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.0 200 OK\r\nSome: header\r\n\r\n", + Response( + status_code=200, + headers=[("Some", "header")], + http_version="1.0", + reason=b"OK", + ), + ) + + # single-character header values (actually disallowed by the ABNF in RFC + # 7230 -- this is a bug in the standard that we originally copied...) + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.0 200 OK\r\n" b"Foo: a a a a a \r\n\r\n", + Response( + status_code=200, + headers=[("Foo", "a a a a a")], + http_version="1.0", + reason=b"OK", + ), + ) + + # Empty headers -- also legal + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.0 200 OK\r\n" b"Foo:\r\n\r\n", + Response( + status_code=200, headers=[("Foo", "")], http_version="1.0", reason=b"OK" + ), + ) + + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.0 200 OK\r\n" b"Foo: \t \t \r\n\r\n", + Response( + status_code=200, headers=[("Foo", "")], http_version="1.0", reason=b"OK" + ), + ) + + # Tolerate broken servers that leave off the response code + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.0 200\r\n" b"Foo: bar\r\n\r\n", + Response( + status_code=200, headers=[("Foo", "bar")], http_version="1.0", reason=b"" + ), + ) + + # Tolerate headers line endings (\r\n and \n) + # \n\r\b between headers and body + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.1 200 OK\r\nSomeHeader: val\n\r\n", + Response( + status_code=200, + headers=[("SomeHeader", "val")], + http_version="1.1", + reason="OK", + ), + ) + + # delimited only with \n + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.1 200 OK\nSomeHeader1: val1\nSomeHeader2: val2\n\n", + Response( + status_code=200, + headers=[("SomeHeader1", "val1"), ("SomeHeader2", "val2")], + http_version="1.1", + reason="OK", + ), + ) + + # mixed \r\n and \n + tr( + READERS[SERVER, SEND_RESPONSE], + b"HTTP/1.1 200 OK\r\nSomeHeader1: val1\nSomeHeader2: val2\n\r\n", + Response( + status_code=200, + headers=[("SomeHeader1", "val1"), ("SomeHeader2", "val2")], + http_version="1.1", + reason="OK", + ), + ) + + # obsolete line folding + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1\r\n" + b"Host: example.com\r\n" + b"Some: multi-line\r\n" + b" header\r\n" + b"\tnonsense\r\n" + b" \t \t\tI guess\r\n" + b"Connection: close\r\n" + b"More-nonsense: in the\r\n" + b" last header \r\n\r\n", + Request( + method="HEAD", + target="/foo", + headers=[ + ("Host", "example.com"), + ("Some", "multi-line header nonsense I guess"), + ("Connection", "close"), + ("More-nonsense", "in the last header"), + ], + ), + ) + + with pytest.raises(LocalProtocolError): + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1\r\n" b" folded: line\r\n\r\n", + None, + ) + + with pytest.raises(LocalProtocolError): + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1\r\n" b"foo : line\r\n\r\n", + None, + ) + with pytest.raises(LocalProtocolError): + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1\r\n" b"foo\t: line\r\n\r\n", + None, + ) + with pytest.raises(LocalProtocolError): + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1\r\n" b"foo\t: line\r\n\r\n", + None, + ) + with pytest.raises(LocalProtocolError): + tr(READERS[CLIENT, IDLE], b"HEAD /foo HTTP/1.1\r\n" b": line\r\n\r\n", None) + + +def test__obsolete_line_fold_bytes() -> None: + # _obsolete_line_fold has a defensive cast to bytearray, which is + # necessary to protect against O(n^2) behavior in case anyone ever passes + # in regular bytestrings... but right now we never pass in regular + # bytestrings. so this test just exists to get some coverage on that + # defensive cast. + assert list(_obsolete_line_fold([b"aaa", b"bbb", b" ccc", b"ddd"])) == [ + b"aaa", + bytearray(b"bbb ccc"), + b"ddd", + ] + + +def _run_reader_iter( + reader: Any, buf: bytes, do_eof: bool +) -> Generator[Any, None, None]: + while True: + event = reader(buf) + if event is None: + break + yield event + # body readers have undefined behavior after returning EndOfMessage, + # because this changes the state so they don't get called again + if type(event) is EndOfMessage: + break + if do_eof: + assert not buf + yield reader.read_eof() + + +def _run_reader(*args: Any) -> List[Event]: + events = list(_run_reader_iter(*args)) + return normalize_data_events(events) + + +def t_body_reader(thunk: Any, data: bytes, expected: Any, do_eof: bool = False) -> None: + # Simple: consume whole thing + print("Test 1") + buf = makebuf(data) + assert _run_reader(thunk(), buf, do_eof) == expected + + # Incrementally growing buffer + print("Test 2") + reader = thunk() + buf = ReceiveBuffer() + events = [] + for i in range(len(data)): + events += _run_reader(reader, buf, False) + buf += data[i : i + 1] + events += _run_reader(reader, buf, do_eof) + assert normalize_data_events(events) == expected + + is_complete = any(type(event) is EndOfMessage for event in expected) + if is_complete and not do_eof: + buf = makebuf(data + b"trailing") + assert _run_reader(thunk(), buf, False) == expected + + +def test_ContentLengthReader() -> None: + t_body_reader(lambda: ContentLengthReader(0), b"", [EndOfMessage()]) + + t_body_reader( + lambda: ContentLengthReader(10), + b"0123456789", + [Data(data=b"0123456789"), EndOfMessage()], + ) + + +def test_Http10Reader() -> None: + t_body_reader(Http10Reader, b"", [EndOfMessage()], do_eof=True) + t_body_reader(Http10Reader, b"asdf", [Data(data=b"asdf")], do_eof=False) + t_body_reader( + Http10Reader, b"asdf", [Data(data=b"asdf"), EndOfMessage()], do_eof=True + ) + + +def test_ChunkedReader() -> None: + t_body_reader(ChunkedReader, b"0\r\n\r\n", [EndOfMessage()]) + + t_body_reader( + ChunkedReader, + b"0\r\nSome: header\r\n\r\n", + [EndOfMessage(headers=[("Some", "header")])], + ) + + t_body_reader( + ChunkedReader, + b"5\r\n01234\r\n" + + b"10\r\n0123456789abcdef\r\n" + + b"0\r\n" + + b"Some: header\r\n\r\n", + [ + Data(data=b"012340123456789abcdef"), + EndOfMessage(headers=[("Some", "header")]), + ], + ) + + t_body_reader( + ChunkedReader, + b"5\r\n01234\r\n" + b"10\r\n0123456789abcdef\r\n" + b"0\r\n\r\n", + [Data(data=b"012340123456789abcdef"), EndOfMessage()], + ) + + # handles upper and lowercase hex + t_body_reader( + ChunkedReader, + b"aA\r\n" + b"x" * 0xAA + b"\r\n" + b"0\r\n\r\n", + [Data(data=b"x" * 0xAA), EndOfMessage()], + ) + + # refuses arbitrarily long chunk integers + with pytest.raises(LocalProtocolError): + # Technically this is legal HTTP/1.1, but we refuse to process chunk + # sizes that don't fit into 20 characters of hex + t_body_reader(ChunkedReader, b"9" * 100 + b"\r\nxxx", [Data(data=b"xxx")]) + + # refuses garbage in the chunk count + with pytest.raises(LocalProtocolError): + t_body_reader(ChunkedReader, b"10\x00\r\nxxx", None) + + # handles (and discards) "chunk extensions" omg wtf + t_body_reader( + ChunkedReader, + b"5; hello=there\r\n" + + b"xxxxx" + + b"\r\n" + + b'0; random="junk"; some=more; canbe=lonnnnngg\r\n\r\n', + [Data(data=b"xxxxx"), EndOfMessage()], + ) + + +def test_ContentLengthWriter() -> None: + w = ContentLengthWriter(5) + assert dowrite(w, Data(data=b"123")) == b"123" + assert dowrite(w, Data(data=b"45")) == b"45" + assert dowrite(w, EndOfMessage()) == b"" + + w = ContentLengthWriter(5) + with pytest.raises(LocalProtocolError): + dowrite(w, Data(data=b"123456")) + + w = ContentLengthWriter(5) + dowrite(w, Data(data=b"123")) + with pytest.raises(LocalProtocolError): + dowrite(w, Data(data=b"456")) + + w = ContentLengthWriter(5) + dowrite(w, Data(data=b"123")) + with pytest.raises(LocalProtocolError): + dowrite(w, EndOfMessage()) + + w = ContentLengthWriter(5) + dowrite(w, Data(data=b"123")) == b"123" + dowrite(w, Data(data=b"45")) == b"45" + with pytest.raises(LocalProtocolError): + dowrite(w, EndOfMessage(headers=[("Etag", "asdf")])) + + +def test_ChunkedWriter() -> None: + w = ChunkedWriter() + assert dowrite(w, Data(data=b"aaa")) == b"3\r\naaa\r\n" + assert dowrite(w, Data(data=b"a" * 20)) == b"14\r\n" + b"a" * 20 + b"\r\n" + + assert dowrite(w, Data(data=b"")) == b"" + + assert dowrite(w, EndOfMessage()) == b"0\r\n\r\n" + + assert ( + dowrite(w, EndOfMessage(headers=[("Etag", "asdf"), ("a", "b")])) + == b"0\r\nEtag: asdf\r\na: b\r\n\r\n" + ) + + +def test_Http10Writer() -> None: + w = Http10Writer() + assert dowrite(w, Data(data=b"1234")) == b"1234" + assert dowrite(w, EndOfMessage()) == b"" + + with pytest.raises(LocalProtocolError): + dowrite(w, EndOfMessage(headers=[("Etag", "asdf")])) + + +def test_reject_garbage_after_request_line() -> None: + with pytest.raises(LocalProtocolError): + tr(READERS[SERVER, SEND_RESPONSE], b"HTTP/1.0 200 OK\x00xxxx\r\n\r\n", None) + + +def test_reject_garbage_after_response_line() -> None: + with pytest.raises(LocalProtocolError): + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1 xxxxxx\r\n" b"Host: a\r\n\r\n", + None, + ) + + +def test_reject_garbage_in_header_line() -> None: + with pytest.raises(LocalProtocolError): + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1\r\n" b"Host: foo\x00bar\r\n\r\n", + None, + ) + + +def test_reject_non_vchar_in_path() -> None: + for bad_char in b"\x00\x20\x7f\xee": + message = bytearray(b"HEAD /") + message.append(bad_char) + message.extend(b" HTTP/1.1\r\nHost: foobar\r\n\r\n") + with pytest.raises(LocalProtocolError): + tr(READERS[CLIENT, IDLE], message, None) + + +# https://github.com/python-hyper/h11/issues/57 +def test_allow_some_garbage_in_cookies() -> None: + tr( + READERS[CLIENT, IDLE], + b"HEAD /foo HTTP/1.1\r\n" + b"Host: foo\r\n" + b"Set-Cookie: ___utmvafIumyLc=kUd\x01UpAt; path=/; Max-Age=900\r\n" + b"\r\n", + Request( + method="HEAD", + target="/foo", + headers=[ + ("Host", "foo"), + ("Set-Cookie", "___utmvafIumyLc=kUd\x01UpAt; path=/; Max-Age=900"), + ], + ), + ) + + +def test_host_comes_first() -> None: + tw( + write_headers, + normalize_and_validate([("foo", "bar"), ("Host", "example.com")]), + b"Host: example.com\r\nfoo: bar\r\n\r\n", + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_receivebuffer.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_receivebuffer.py new file mode 100644 index 00000000..21a3870b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_receivebuffer.py @@ -0,0 +1,135 @@ +import re +from typing import Tuple + +import pytest + +from .._receivebuffer import ReceiveBuffer + + +def test_receivebuffer() -> None: + b = ReceiveBuffer() + assert not b + assert len(b) == 0 + assert bytes(b) == b"" + + b += b"123" + assert b + assert len(b) == 3 + assert bytes(b) == b"123" + + assert bytes(b) == b"123" + + assert b.maybe_extract_at_most(2) == b"12" + assert b + assert len(b) == 1 + assert bytes(b) == b"3" + + assert bytes(b) == b"3" + + assert b.maybe_extract_at_most(10) == b"3" + assert bytes(b) == b"" + + assert b.maybe_extract_at_most(10) is None + assert not b + + ################################################################ + # maybe_extract_until_next + ################################################################ + + b += b"123\n456\r\n789\r\n" + + assert b.maybe_extract_next_line() == b"123\n456\r\n" + assert bytes(b) == b"789\r\n" + + assert b.maybe_extract_next_line() == b"789\r\n" + assert bytes(b) == b"" + + b += b"12\r" + assert b.maybe_extract_next_line() is None + assert bytes(b) == b"12\r" + + b += b"345\n\r" + assert b.maybe_extract_next_line() is None + assert bytes(b) == b"12\r345\n\r" + + # here we stopped at the middle of b"\r\n" delimiter + + b += b"\n6789aaa123\r\n" + assert b.maybe_extract_next_line() == b"12\r345\n\r\n" + assert b.maybe_extract_next_line() == b"6789aaa123\r\n" + assert b.maybe_extract_next_line() is None + assert bytes(b) == b"" + + ################################################################ + # maybe_extract_lines + ################################################################ + + b += b"123\r\na: b\r\nfoo:bar\r\n\r\ntrailing" + lines = b.maybe_extract_lines() + assert lines == [b"123", b"a: b", b"foo:bar"] + assert bytes(b) == b"trailing" + + assert b.maybe_extract_lines() is None + + b += b"\r\n\r" + assert b.maybe_extract_lines() is None + + assert b.maybe_extract_at_most(100) == b"trailing\r\n\r" + assert not b + + # Empty body case (as happens at the end of chunked encoding if there are + # no trailing headers, e.g.) + b += b"\r\ntrailing" + assert b.maybe_extract_lines() == [] + assert bytes(b) == b"trailing" + + +@pytest.mark.parametrize( + "data", + [ + pytest.param( + ( + b"HTTP/1.1 200 OK\r\n", + b"Content-type: text/plain\r\n", + b"Connection: close\r\n", + b"\r\n", + b"Some body", + ), + id="with_crlf_delimiter", + ), + pytest.param( + ( + b"HTTP/1.1 200 OK\n", + b"Content-type: text/plain\n", + b"Connection: close\n", + b"\n", + b"Some body", + ), + id="with_lf_only_delimiter", + ), + pytest.param( + ( + b"HTTP/1.1 200 OK\n", + b"Content-type: text/plain\r\n", + b"Connection: close\n", + b"\n", + b"Some body", + ), + id="with_mixed_crlf_and_lf", + ), + ], +) +def test_receivebuffer_for_invalid_delimiter(data: Tuple[bytes]) -> None: + b = ReceiveBuffer() + + for line in data: + b += line + + lines = b.maybe_extract_lines() + + assert lines == [ + b"HTTP/1.1 200 OK", + b"Content-type: text/plain", + b"Connection: close", + ] + assert bytes(b) == b"Some body" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_state.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_state.py new file mode 100644 index 00000000..bc974e63 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_state.py @@ -0,0 +1,271 @@ +import pytest + +from .._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from .._state import ( + _SWITCH_CONNECT, + _SWITCH_UPGRADE, + CLIENT, + CLOSED, + ConnectionState, + DONE, + IDLE, + MIGHT_SWITCH_PROTOCOL, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, + SWITCHED_PROTOCOL, +) +from .._util import LocalProtocolError + + +def test_ConnectionState() -> None: + cs = ConnectionState() + + # Basic event-triggered transitions + + assert cs.states == {CLIENT: IDLE, SERVER: IDLE} + + cs.process_event(CLIENT, Request) + # The SERVER-Request special case: + assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} + + # Illegal transitions raise an error and nothing happens + with pytest.raises(LocalProtocolError): + cs.process_event(CLIENT, Request) + assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} + + cs.process_event(SERVER, InformationalResponse) + assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} + + cs.process_event(SERVER, Response) + assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_BODY} + + cs.process_event(CLIENT, EndOfMessage) + cs.process_event(SERVER, EndOfMessage) + assert cs.states == {CLIENT: DONE, SERVER: DONE} + + # State-triggered transition + + cs.process_event(SERVER, ConnectionClosed) + assert cs.states == {CLIENT: MUST_CLOSE, SERVER: CLOSED} + + +def test_ConnectionState_keep_alive() -> None: + # keep_alive = False + cs = ConnectionState() + cs.process_event(CLIENT, Request) + cs.process_keep_alive_disabled() + cs.process_event(CLIENT, EndOfMessage) + assert cs.states == {CLIENT: MUST_CLOSE, SERVER: SEND_RESPONSE} + + cs.process_event(SERVER, Response) + cs.process_event(SERVER, EndOfMessage) + assert cs.states == {CLIENT: MUST_CLOSE, SERVER: MUST_CLOSE} + + +def test_ConnectionState_keep_alive_in_DONE() -> None: + # Check that if keep_alive is disabled when the CLIENT is already in DONE, + # then this is sufficient to immediately trigger the DONE -> MUST_CLOSE + # transition + cs = ConnectionState() + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, EndOfMessage) + assert cs.states[CLIENT] is DONE + cs.process_keep_alive_disabled() + assert cs.states[CLIENT] is MUST_CLOSE + + +def test_ConnectionState_switch_denied() -> None: + for switch_type in (_SWITCH_CONNECT, _SWITCH_UPGRADE): + for deny_early in (True, False): + cs = ConnectionState() + cs.process_client_switch_proposal(switch_type) + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, Data) + assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} + + assert switch_type in cs.pending_switch_proposals + + if deny_early: + # before client reaches DONE + cs.process_event(SERVER, Response) + assert not cs.pending_switch_proposals + + cs.process_event(CLIENT, EndOfMessage) + + if deny_early: + assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} + else: + assert cs.states == { + CLIENT: MIGHT_SWITCH_PROTOCOL, + SERVER: SEND_RESPONSE, + } + + cs.process_event(SERVER, InformationalResponse) + assert cs.states == { + CLIENT: MIGHT_SWITCH_PROTOCOL, + SERVER: SEND_RESPONSE, + } + + cs.process_event(SERVER, Response) + assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} + assert not cs.pending_switch_proposals + + +_response_type_for_switch = { + _SWITCH_UPGRADE: InformationalResponse, + _SWITCH_CONNECT: Response, + None: Response, +} + + +def test_ConnectionState_protocol_switch_accepted() -> None: + for switch_event in [_SWITCH_UPGRADE, _SWITCH_CONNECT]: + cs = ConnectionState() + cs.process_client_switch_proposal(switch_event) + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, Data) + assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} + + cs.process_event(CLIENT, EndOfMessage) + assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} + + cs.process_event(SERVER, InformationalResponse) + assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} + + cs.process_event(SERVER, _response_type_for_switch[switch_event], switch_event) + assert cs.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} + + +def test_ConnectionState_double_protocol_switch() -> None: + # CONNECT + Upgrade is legal! Very silly, but legal. So we support + # it. Because sometimes doing the silly thing is easier than not. + for server_switch in [None, _SWITCH_UPGRADE, _SWITCH_CONNECT]: + cs = ConnectionState() + cs.process_client_switch_proposal(_SWITCH_UPGRADE) + cs.process_client_switch_proposal(_SWITCH_CONNECT) + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, EndOfMessage) + assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} + cs.process_event( + SERVER, _response_type_for_switch[server_switch], server_switch + ) + if server_switch is None: + assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} + else: + assert cs.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} + + +def test_ConnectionState_inconsistent_protocol_switch() -> None: + for client_switches, server_switch in [ + ([], _SWITCH_CONNECT), + ([], _SWITCH_UPGRADE), + ([_SWITCH_UPGRADE], _SWITCH_CONNECT), + ([_SWITCH_CONNECT], _SWITCH_UPGRADE), + ]: + cs = ConnectionState() + for client_switch in client_switches: # type: ignore[attr-defined] + cs.process_client_switch_proposal(client_switch) + cs.process_event(CLIENT, Request) + with pytest.raises(LocalProtocolError): + cs.process_event(SERVER, Response, server_switch) + + +def test_ConnectionState_keepalive_protocol_switch_interaction() -> None: + # keep_alive=False + pending_switch_proposals + cs = ConnectionState() + cs.process_client_switch_proposal(_SWITCH_UPGRADE) + cs.process_event(CLIENT, Request) + cs.process_keep_alive_disabled() + cs.process_event(CLIENT, Data) + assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} + + # the protocol switch "wins" + cs.process_event(CLIENT, EndOfMessage) + assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} + + # but when the server denies the request, keep_alive comes back into play + cs.process_event(SERVER, Response) + assert cs.states == {CLIENT: MUST_CLOSE, SERVER: SEND_BODY} + + +def test_ConnectionState_reuse() -> None: + cs = ConnectionState() + + with pytest.raises(LocalProtocolError): + cs.start_next_cycle() + + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, EndOfMessage) + + with pytest.raises(LocalProtocolError): + cs.start_next_cycle() + + cs.process_event(SERVER, Response) + cs.process_event(SERVER, EndOfMessage) + + cs.start_next_cycle() + assert cs.states == {CLIENT: IDLE, SERVER: IDLE} + + # No keepalive + + cs.process_event(CLIENT, Request) + cs.process_keep_alive_disabled() + cs.process_event(CLIENT, EndOfMessage) + cs.process_event(SERVER, Response) + cs.process_event(SERVER, EndOfMessage) + + with pytest.raises(LocalProtocolError): + cs.start_next_cycle() + + # One side closed + + cs = ConnectionState() + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, EndOfMessage) + cs.process_event(CLIENT, ConnectionClosed) + cs.process_event(SERVER, Response) + cs.process_event(SERVER, EndOfMessage) + + with pytest.raises(LocalProtocolError): + cs.start_next_cycle() + + # Succesful protocol switch + + cs = ConnectionState() + cs.process_client_switch_proposal(_SWITCH_UPGRADE) + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, EndOfMessage) + cs.process_event(SERVER, InformationalResponse, _SWITCH_UPGRADE) + + with pytest.raises(LocalProtocolError): + cs.start_next_cycle() + + # Failed protocol switch + + cs = ConnectionState() + cs.process_client_switch_proposal(_SWITCH_UPGRADE) + cs.process_event(CLIENT, Request) + cs.process_event(CLIENT, EndOfMessage) + cs.process_event(SERVER, Response) + cs.process_event(SERVER, EndOfMessage) + + cs.start_next_cycle() + assert cs.states == {CLIENT: IDLE, SERVER: IDLE} + + +def test_server_request_is_illegal() -> None: + # There used to be a bug in how we handled the Request special case that + # made this allowed... + cs = ConnectionState() + with pytest.raises(LocalProtocolError): + cs.process_event(SERVER, Request) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_util.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_util.py new file mode 100644 index 00000000..1637919b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/h11/tests/test_util.py @@ -0,0 +1,112 @@ +import re +import sys +import traceback +from typing import NoReturn + +import pytest + +from .._util import ( + bytesify, + LocalProtocolError, + ProtocolError, + RemoteProtocolError, + Sentinel, + validate, +) + + +def test_ProtocolError() -> None: + with pytest.raises(TypeError): + ProtocolError("abstract base class") + + +def test_LocalProtocolError() -> None: + try: + raise LocalProtocolError("foo") + except LocalProtocolError as e: + assert str(e) == "foo" + assert e.error_status_hint == 400 + + try: + raise LocalProtocolError("foo", error_status_hint=418) + except LocalProtocolError as e: + assert str(e) == "foo" + assert e.error_status_hint == 418 + + def thunk() -> NoReturn: + raise LocalProtocolError("a", error_status_hint=420) + + try: + try: + thunk() + except LocalProtocolError as exc1: + orig_traceback = "".join(traceback.format_tb(sys.exc_info()[2])) + exc1._reraise_as_remote_protocol_error() + except RemoteProtocolError as exc2: + assert type(exc2) is RemoteProtocolError + assert exc2.args == ("a",) + assert exc2.error_status_hint == 420 + new_traceback = "".join(traceback.format_tb(sys.exc_info()[2])) + assert new_traceback.endswith(orig_traceback) + + +def test_validate() -> None: + my_re = re.compile(br"(?P[0-9]+)\.(?P[0-9]+)") + with pytest.raises(LocalProtocolError): + validate(my_re, b"0.") + + groups = validate(my_re, b"0.1") + assert groups == {"group1": b"0", "group2": b"1"} + + # successful partial matches are an error - must match whole string + with pytest.raises(LocalProtocolError): + validate(my_re, b"0.1xx") + with pytest.raises(LocalProtocolError): + validate(my_re, b"0.1\n") + + +def test_validate_formatting() -> None: + my_re = re.compile(br"foo") + + with pytest.raises(LocalProtocolError) as excinfo: + validate(my_re, b"", "oops") + assert "oops" in str(excinfo.value) + + with pytest.raises(LocalProtocolError) as excinfo: + validate(my_re, b"", "oops {}") + assert "oops {}" in str(excinfo.value) + + with pytest.raises(LocalProtocolError) as excinfo: + validate(my_re, b"", "oops {} xx", 10) + assert "oops 10 xx" in str(excinfo.value) + + +def test_make_sentinel() -> None: + class S(Sentinel, metaclass=Sentinel): + pass + + assert repr(S) == "S" + assert S == S + assert type(S).__name__ == "S" + assert S in {S} + assert type(S) is S + + class S2(Sentinel, metaclass=Sentinel): + pass + + assert repr(S2) == "S2" + assert S != S2 + assert S not in {S2} + assert type(S) is not type(S2) + + +def test_bytesify() -> None: + assert bytesify(b"123") == b"123" + assert bytesify(bytearray(b"123")) == b"123" + assert bytesify("123") == b"123" + + with pytest.raises(UnicodeEncodeError): + bytesify("\u1234") + + with pytest.raises(TypeError): + bytesify(10) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/LICENSE new file mode 100644 index 00000000..79a03ca5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/METADATA new file mode 100644 index 00000000..1e6aeab5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/METADATA @@ -0,0 +1,135 @@ +Metadata-Version: 2.1 +Name: httptools +Version: 0.4.0 +Summary: A collection of framework independent HTTP protocol utils. +Home-page: https://github.com/MagicStack/httptools +Author: Yury Selivanov +Author-email: yury@magic.io +License: MIT +Platform: macOS +Platform: POSIX +Platform: Windows +Classifier: License :: OSI Approved :: MIT License +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.5.0 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: test +Requires-Dist: Cython (<0.30.0,>=0.29.24) ; extra == 'test' + +![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. Install development requirements with `pip install -e .[test]` + +5. Run `make` and `make test`. + + +# License + +MIT. + + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/RECORD new file mode 100644 index 00000000..811bc4a3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/RECORD @@ -0,0 +1,18 @@ +httptools-0.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +httptools-0.4.0.dist-info/LICENSE,sha256=HAKLBZ16WOFMzaOMq87WmMWR_mFP--T3IUMERuhsjWk,1114 +httptools-0.4.0.dist-info/METADATA,sha256=SPBw4NDQwGZinZd69ZJt4v5SQMU-1gcJmjeRT47LOkw,3597 +httptools-0.4.0.dist-info/RECORD,, +httptools-0.4.0.dist-info/WHEEL,sha256=OmDKD3JmZjhMu_YdpkiJDfFL1rf8n9nexhWCGhSBGVE,101 +httptools-0.4.0.dist-info/top_level.txt,sha256=APjJKTbZcj0OQ4fdgf2eTCk82nK1n2BFXOD7ky41MPY,10 +httptools/__init__.py,sha256=uWLIa0nghlhLGoS8My_6YVhUlFbv3FhYsvxYpZHecS8,153 +httptools/__pycache__/__init__.cpython-37.pyc,, +httptools/__pycache__/_version.cpython-37.pyc,, +httptools/_version.py,sha256=jNecmUTYiNqpt3WCDHjdZbEqrAYBV8iD_ZN-kfjLz9I,588 +httptools/parser/__init__.py,sha256=1XGlLzcfsdWYFehxDHaQJUl7RhWnSwG9hWpVkUKK50g,171 +httptools/parser/__pycache__/__init__.cpython-37.pyc,, +httptools/parser/__pycache__/errors.cpython-37.pyc,, +httptools/parser/errors.py,sha256=fQeEGiZ6AQH7SIa-7uzMs5QggoXr0A8YBPVHmafSw5Q,596 +httptools/parser/parser.c,sha256=Vrbwy_G-dwwPCsSNOcQNklEumZXhwls8wbSVLmU2uFQ,400467 +httptools/parser/parser.cp37-win_amd64.pyd,sha256=b9aztssGMqqLNHInYUMEFg48v71APKBKudMIlGLev3M,83968 +httptools/parser/url_parser.c,sha256=h45G5o5mKPlwODL3NyQ_u3NqGCsR4r0jaPgKHQt1LE8,236857 +httptools/parser/url_parser.cp37-win_amd64.pyd,sha256=YZXzMhPJySbxRqdSrcz73jgsv8xiBGaxYf3F8MKg7u8,39424 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/WHEEL new file mode 100644 index 00000000..54091f94 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: false +Tag: cp37-cp37m-win_amd64 + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/top_level.txt new file mode 100644 index 00000000..bef3b40b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools-0.4.0.dist-info/top_level.txt @@ -0,0 +1 @@ +httptools diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/__init__.py new file mode 100644 index 00000000..972053ef --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/_version.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/_version.py new file mode 100644 index 00000000..adce8989 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/_version.py @@ -0,0 +1,13 @@ +# This file MUST NOT contain anything but the __version__ assignment. +# +# When making a release, change the value of __version__ +# to an appropriate value, and open a pull request against +# the correct branch (master if making a new feature release). +# The commit message MUST contain a properly formatted release +# log, and the commit must be signed. +# +# The release automation will: build and test the packages for the +# supported platforms, publish the packages on PyPI, merge the PR +# to the target branch, create a Git tag pointing to the commit. + +__version__ = '0.4.0' diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/__init__.py new file mode 100644 index 00000000..ba371f5e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/__init__.py @@ -0,0 +1,5 @@ +from .parser import * # NoQA +from .errors import * # NoQA +from .url_parser import * # NoQA + +__all__ = parser.__all__ + errors.__all__ + url_parser.__all__ # NoQA diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/errors.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/errors.py new file mode 100644 index 00000000..bc24c466 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/errors.py @@ -0,0 +1,30 @@ +__all__ = ('HttpParserError', + 'HttpParserCallbackError', + 'HttpParserInvalidStatusError', + 'HttpParserInvalidMethodError', + 'HttpParserInvalidURLError', + 'HttpParserUpgrade') + + +class HttpParserError(Exception): + pass + + +class HttpParserCallbackError(HttpParserError): + pass + + +class HttpParserInvalidStatusError(HttpParserError): + pass + + +class HttpParserInvalidMethodError(HttpParserError): + pass + + +class HttpParserInvalidURLError(HttpParserError): + pass + + +class HttpParserUpgrade(Exception): + pass diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/parser.c b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/parser.c new file mode 100644 index 00000000..6e4778ae --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/parser.c @@ -0,0 +1,10421 @@ +/* Generated by Cython 0.29.28 */ + +/* BEGIN: Cython Metadata +{ + "distutils": { + "depends": [], + "extra_compile_args": [ + "-O2" + ], + "name": "httptools.parser.parser", + "sources": [ + "httptools/parser/parser.pyx" + ] + }, + "module_name": "httptools.parser.parser" +} +END: Cython Metadata */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_28" +#define CYTHON_HEX_VERSION 0x001D1CF0 +#define CYTHON_FUTURE_DIVISION 1 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030B00A1) + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif +#endif + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #endif +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#ifndef PyObject_Unicode + #define PyObject_Unicode PyObject_Str +#endif +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(WIN32) || defined(MS_WINDOWS) + #define _USE_MATH_DEFINES +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#define __PYX_MARK_ERR_POS(f_index, lineno) \ + { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__httptools__parser__parser +#define __PYX_HAVE_API__httptools__parser__parser +/* Early includes */ +#include +#include +#include "pythread.h" +#include +#include "llhttp.h" +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + + +static const char *__pyx_f[] = { + "httptools\\parser\\parser.pyx", + "stringsource", + "type.pxd", + "bool.pxd", + "complex.pxd", +}; + +/*--- Type declarations ---*/ +struct __pyx_obj_9httptools_6parser_6parser_HttpParser; +struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser; +struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser; + +/* "httptools/parser/parser.pyx":26 + * + * @cython.internal + * cdef class HttpParser: # <<<<<<<<<<<<<< + * + * cdef: + */ +struct __pyx_obj_9httptools_6parser_6parser_HttpParser { + PyObject_HEAD + struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *__pyx_vtab; + llhttp_t *_cparser; + llhttp_settings_t *_csettings; + PyObject *_current_header_name; + PyObject *_current_header_value; + PyObject *_proto_on_url; + PyObject *_proto_on_status; + PyObject *_proto_on_body; + PyObject *_proto_on_header; + PyObject *_proto_on_headers_complete; + PyObject *_proto_on_message_complete; + PyObject *_proto_on_chunk_header; + PyObject *_proto_on_chunk_complete; + PyObject *_proto_on_message_begin; + PyObject *_last_error; + Py_buffer py_buf; +}; + + +/* "httptools/parser/parser.pyx":215 + * + * + * cdef class HttpRequestParser(HttpParser): # <<<<<<<<<<<<<< + * + * def __init__(self, protocol): + */ +struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser __pyx_base; +}; + + +/* "httptools/parser/parser.pyx":229 + * + * + * cdef class HttpResponseParser(HttpParser): # <<<<<<<<<<<<<< + * + * def __init__(self, protocol): + */ +struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser __pyx_base; +}; + + + +/* "httptools/parser/parser.pyx":26 + * + * @cython.internal + * cdef class HttpParser: # <<<<<<<<<<<<<< + * + * cdef: + */ + +struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser { + PyObject *(*_init)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *, PyObject *, llhttp_type_t); + PyObject *(*_maybe_call_on_header)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *); + PyObject *(*_on_header_field)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *, PyObject *); + PyObject *(*_on_header_value)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *, PyObject *); + PyObject *(*_on_headers_complete)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *); + PyObject *(*_on_chunk_header)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *); + PyObject *(*_on_chunk_complete)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *); +}; +static struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *__pyx_vtabptr_9httptools_6parser_6parser_HttpParser; + + +/* "httptools/parser/parser.pyx":215 + * + * + * cdef class HttpRequestParser(HttpParser): # <<<<<<<<<<<<<< + * + * def __init__(self, protocol): + */ + +struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpRequestParser { + struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser __pyx_base; +}; +static struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpRequestParser *__pyx_vtabptr_9httptools_6parser_6parser_HttpRequestParser; + + +/* "httptools/parser/parser.pyx":229 + * + * + * cdef class HttpResponseParser(HttpParser): # <<<<<<<<<<<<<< + * + * def __init__(self, protocol): + */ + +struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpResponseParser { + struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser __pyx_base; +}; +static struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpResponseParser *__pyx_vtabptr_9httptools_6parser_6parser_HttpResponseParser; + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* KeywordStringCheck.proto */ +static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); + +/* PyErrExceptionMatches.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* GetAttr.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); + +/* GetAttr3.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif +#if CYTHON_FAST_PYCALL + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* PyObjectCall2Args.proto */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); + +/* RaiseException.proto */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* GetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* SwapException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSwap(type, value, tb) __Pyx__ExceptionSwap(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* GetTopmostException.proto */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* SaveResetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +#else +#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) +#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) +#endif + +/* PyObjectSetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +#define __Pyx_PyObject_DelAttrStr(o,n) __Pyx_PyObject_SetAttrStr(o, n, NULL) +static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value); +#else +#define __Pyx_PyObject_DelAttrStr(o,n) PyObject_DelAttr(o,n) +#define __Pyx_PyObject_SetAttrStr(o,n,v) PyObject_SetAttr(o,n,v) +#endif + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* decode_c_string_utf16.proto */ +static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16(const char *s, Py_ssize_t size, const char *errors) { + int byteorder = 0; + return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); +} +static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16LE(const char *s, Py_ssize_t size, const char *errors) { + int byteorder = -1; + return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); +} +static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16BE(const char *s, Py_ssize_t size, const char *errors) { + int byteorder = 1; + return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); +} + +/* decode_c_bytes.proto */ +static CYTHON_INLINE PyObject* __Pyx_decode_c_bytes( + const char* cstring, Py_ssize_t length, Py_ssize_t start, Py_ssize_t stop, + const char* encoding, const char* errors, + PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)); + +/* decode_bytes.proto */ +static CYTHON_INLINE PyObject* __Pyx_decode_bytes( + PyObject* string, Py_ssize_t start, Py_ssize_t stop, + const char* encoding, const char* errors, + PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { + return __Pyx_decode_c_bytes( + PyBytes_AS_STRING(string), PyBytes_GET_SIZE(string), + start, stop, encoding, errors, decode_func); +} + +/* PyObject_GenericGetAttrNoDict.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr +#endif + +/* PyObject_GenericGetAttr.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr +#endif + +/* SetVTable.proto */ +static int __Pyx_SetVtable(PyObject *dict, void *vtable); + +/* PyObjectGetAttrStrNoError.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); + +/* SetupReduce.proto */ +static int __Pyx_setup_reduce(PyObject* type_obj); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto +#define __PYX_HAVE_RT_ImportType_proto +enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 +}; +static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); +#endif + +/* Import.proto */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); + +/* ImportFrom.proto */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint8_t(uint8_t value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_ptrdiff_t(ptrdiff_t value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint16_t(uint16_t value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__init(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_protocol, llhttp_type_t __pyx_v_mode); /* proto*/ +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__maybe_call_on_header(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto*/ +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_header_field(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_field); /* proto*/ +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_header_value(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_val); /* proto*/ +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_headers_complete(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto*/ +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_chunk_header(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto*/ +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_chunk_complete(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto*/ + +/* Module declarations from 'cpython.mem' */ + +/* Module declarations from 'cpython.version' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.type' */ +static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; + +/* Module declarations from 'libc.string' */ + +/* Module declarations from 'libc.stdio' */ + +/* Module declarations from 'cpython.object' */ + +/* Module declarations from 'cpython.ref' */ + +/* Module declarations from 'cpython.exc' */ + +/* Module declarations from 'cpython.module' */ + +/* Module declarations from 'cpython.tuple' */ + +/* Module declarations from 'cpython.list' */ + +/* Module declarations from 'cpython.sequence' */ + +/* Module declarations from 'cpython.mapping' */ + +/* Module declarations from 'cpython.iterator' */ + +/* Module declarations from 'cpython.number' */ + +/* Module declarations from 'cpython.int' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.bool' */ +static PyTypeObject *__pyx_ptype_7cpython_4bool_bool = 0; + +/* Module declarations from 'cpython.long' */ + +/* Module declarations from 'cpython.float' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.complex' */ +static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0; + +/* Module declarations from 'cpython.string' */ + +/* Module declarations from 'cpython.unicode' */ + +/* Module declarations from 'cpython.dict' */ + +/* Module declarations from 'cpython.instance' */ + +/* Module declarations from 'cpython.function' */ + +/* Module declarations from 'cpython.method' */ + +/* Module declarations from 'cpython.weakref' */ + +/* Module declarations from 'cpython.getargs' */ + +/* Module declarations from 'cpython.pythread' */ + +/* Module declarations from 'cpython.pystate' */ + +/* Module declarations from 'cpython.cobject' */ + +/* Module declarations from 'cpython.oldbuffer' */ + +/* Module declarations from 'cpython.set' */ + +/* Module declarations from 'cpython.buffer' */ + +/* Module declarations from 'cpython.bytes' */ + +/* Module declarations from 'cpython.pycapsule' */ + +/* Module declarations from 'cpython' */ + +/* Module declarations from 'httptools.parser.python' */ + +/* Module declarations from 'cython' */ + +/* Module declarations from 'httptools.parser' */ + +/* Module declarations from 'libc.stdint' */ + +/* Module declarations from 'httptools.parser.cparser' */ + +/* Module declarations from 'httptools.parser.parser' */ +static PyTypeObject *__pyx_ptype_9httptools_6parser_6parser_HttpParser = 0; +static PyTypeObject *__pyx_ptype_9httptools_6parser_6parser_HttpRequestParser = 0; +static PyTypeObject *__pyx_ptype_9httptools_6parser_6parser_HttpResponseParser = 0; +static int __pyx_f_9httptools_6parser_6parser_cb_on_message_begin(llhttp_t *); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_url(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_status(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_header_field(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_header_value(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_headers_complete(llhttp_t *); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_body(llhttp_t *, char const *, size_t); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_message_complete(llhttp_t *); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_chunk_header(llhttp_t *); /*proto*/ +static int __pyx_f_9httptools_6parser_6parser_cb_on_chunk_complete(llhttp_t *); /*proto*/ +static PyObject *__pyx_f_9httptools_6parser_6parser_parser_error_from_errno(llhttp_t *, llhttp_errno_t); /*proto*/ +#define __Pyx_MODULE_NAME "httptools.parser.parser" +extern int __pyx_module_is_main_httptools__parser__parser; +int __pyx_module_is_main_httptools__parser__parser = 0; + +/* Implementation of 'httptools.parser.parser' */ +static PyObject *__pyx_builtin_MemoryError; +static PyObject *__pyx_builtin_TypeError; +static PyObject *__pyx_builtin_BaseException; +static const char __pyx_k_[] = "{}.{}"; +static const char __pyx_k_all[] = "__all__"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_errors[] = "errors"; +static const char __pyx_k_format[] = "format"; +static const char __pyx_k_import[] = "__import__"; +static const char __pyx_k_on_url[] = "on_url"; +static const char __pyx_k_reduce[] = "__reduce__"; +static const char __pyx_k_context[] = "__context__"; +static const char __pyx_k_on_body[] = "on_body"; +static const char __pyx_k_getstate[] = "__getstate__"; +static const char __pyx_k_protocol[] = "protocol"; +static const char __pyx_k_setstate[] = "__setstate__"; +static const char __pyx_k_TypeError[] = "TypeError"; +static const char __pyx_k_on_header[] = "on_header"; +static const char __pyx_k_on_status[] = "on_status"; +static const char __pyx_k_reduce_ex[] = "__reduce_ex__"; +static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__"; +static const char __pyx_k_MemoryError[] = "MemoryError"; +static const char __pyx_k_BaseException[] = "BaseException"; +static const char __pyx_k_reduce_cython[] = "__reduce_cython__"; +static const char __pyx_k_HttpParserError[] = "HttpParserError"; +static const char __pyx_k_on_chunk_header[] = "on_chunk_header"; +static const char __pyx_k_setstate_cython[] = "__setstate_cython__"; +static const char __pyx_k_on_message_begin[] = "on_message_begin"; +static const char __pyx_k_HttpParserUpgrade[] = "HttpParserUpgrade"; +static const char __pyx_k_HttpRequestParser[] = "HttpRequestParser"; +static const char __pyx_k_on_chunk_complete[] = "on_chunk_complete"; +static const char __pyx_k_HttpResponseParser[] = "HttpResponseParser"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_on_headers_complete[] = "on_headers_complete"; +static const char __pyx_k_on_message_complete[] = "on_message_complete"; +static const char __pyx_k_invalid_headers_state[] = "invalid headers state"; +static const char __pyx_k_HttpParserCallbackError[] = "HttpParserCallbackError"; +static const char __pyx_k_HttpParserInvalidURLError[] = "HttpParserInvalidURLError"; +static const char __pyx_k_HttpParserInvalidMethodError[] = "HttpParserInvalidMethodError"; +static const char __pyx_k_HttpParserInvalidStatusError[] = "HttpParserInvalidStatusError"; +static const char __pyx_k_no_default___reduce___due_to_non[] = "no default __reduce__ due to non-trivial __cinit__"; +static PyObject *__pyx_kp_u_; +static PyObject *__pyx_n_s_BaseException; +static PyObject *__pyx_n_s_HttpParserCallbackError; +static PyObject *__pyx_n_s_HttpParserError; +static PyObject *__pyx_n_s_HttpParserInvalidMethodError; +static PyObject *__pyx_n_s_HttpParserInvalidStatusError; +static PyObject *__pyx_n_s_HttpParserInvalidURLError; +static PyObject *__pyx_n_s_HttpParserUpgrade; +static PyObject *__pyx_n_s_HttpRequestParser; +static PyObject *__pyx_n_u_HttpRequestParser; +static PyObject *__pyx_n_s_HttpResponseParser; +static PyObject *__pyx_n_u_HttpResponseParser; +static PyObject *__pyx_n_s_MemoryError; +static PyObject *__pyx_n_s_TypeError; +static PyObject *__pyx_n_s_all; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_context; +static PyObject *__pyx_n_s_errors; +static PyObject *__pyx_n_s_format; +static PyObject *__pyx_n_s_getstate; +static PyObject *__pyx_n_s_import; +static PyObject *__pyx_kp_u_invalid_headers_state; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_kp_s_no_default___reduce___due_to_non; +static PyObject *__pyx_n_u_on_body; +static PyObject *__pyx_n_u_on_chunk_complete; +static PyObject *__pyx_n_u_on_chunk_header; +static PyObject *__pyx_n_u_on_header; +static PyObject *__pyx_n_u_on_headers_complete; +static PyObject *__pyx_n_u_on_message_begin; +static PyObject *__pyx_n_u_on_message_complete; +static PyObject *__pyx_n_u_on_status; +static PyObject *__pyx_n_u_on_url; +static PyObject *__pyx_n_s_protocol; +static PyObject *__pyx_n_s_pyx_vtable; +static PyObject *__pyx_n_s_reduce; +static PyObject *__pyx_n_s_reduce_cython; +static PyObject *__pyx_n_s_reduce_ex; +static PyObject *__pyx_n_s_setstate; +static PyObject *__pyx_n_s_setstate_cython; +static PyObject *__pyx_n_s_test; +static int __pyx_pf_9httptools_6parser_6parser_10HttpParser___cinit__(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto */ +static void __pyx_pf_9httptools_6parser_6parser_10HttpParser_2__dealloc__(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_4get_http_version(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_6should_keep_alive(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_8should_upgrade(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_10feed_data(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_data); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_12__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_14__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ +static int __pyx_pf_9httptools_6parser_6parser_17HttpRequestParser___init__(struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self, PyObject *__pyx_v_protocol); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_2get_method(struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_6__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ +static int __pyx_pf_9httptools_6parser_6parser_18HttpResponseParser___init__(struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self, PyObject *__pyx_v_protocol); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_2get_status_code(struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_6__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_tp_new_9httptools_6parser_6parser_HttpParser(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new_9httptools_6parser_6parser_HttpRequestParser(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tp_new_9httptools_6parser_6parser_HttpResponseParser(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tuple__2; +static PyObject *__pyx_tuple__3; +static PyObject *__pyx_tuple__4; +static PyObject *__pyx_tuple__5; +static PyObject *__pyx_tuple__6; +static PyObject *__pyx_tuple__7; +static PyObject *__pyx_tuple__8; +/* Late includes */ + +/* "httptools/parser/parser.pyx":44 + * Py_buffer py_buf + * + * def __cinit__(self): # <<<<<<<<<<<<<< + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) + */ + +/* Python wrapper */ +static int __pyx_pw_9httptools_6parser_6parser_10HttpParser_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_9httptools_6parser_6parser_10HttpParser_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0); + if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) { + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;} + if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1; + __pyx_r = __pyx_pf_9httptools_6parser_6parser_10HttpParser___cinit__(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_9httptools_6parser_6parser_10HttpParser___cinit__(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__cinit__", 0); + + /* "httptools/parser/parser.pyx":45 + * + * def __cinit__(self): + * self._cparser = \ # <<<<<<<<<<<<<< + * PyMem_Malloc(sizeof(cparser.llhttp_t)) + * if self._cparser is NULL: + */ + __pyx_v_self->_cparser = ((llhttp_t *)PyMem_Malloc((sizeof(llhttp_t)))); + + /* "httptools/parser/parser.pyx":47 + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) + * if self._cparser is NULL: # <<<<<<<<<<<<<< + * raise MemoryError() + * + */ + __pyx_t_1 = ((__pyx_v_self->_cparser == NULL) != 0); + if (unlikely(__pyx_t_1)) { + + /* "httptools/parser/parser.pyx":48 + * PyMem_Malloc(sizeof(cparser.llhttp_t)) + * if self._cparser is NULL: + * raise MemoryError() # <<<<<<<<<<<<<< + * + * self._csettings = \ + */ + PyErr_NoMemory(); __PYX_ERR(0, 48, __pyx_L1_error) + + /* "httptools/parser/parser.pyx":47 + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) + * if self._cparser is NULL: # <<<<<<<<<<<<<< + * raise MemoryError() + * + */ + } + + /* "httptools/parser/parser.pyx":50 + * raise MemoryError() + * + * self._csettings = \ # <<<<<<<<<<<<<< + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) + * if self._csettings is NULL: + */ + __pyx_v_self->_csettings = ((llhttp_settings_t *)PyMem_Malloc((sizeof(llhttp_settings_t)))); + + /* "httptools/parser/parser.pyx":52 + * self._csettings = \ + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) + * if self._csettings is NULL: # <<<<<<<<<<<<<< + * raise MemoryError() + * + */ + __pyx_t_1 = ((__pyx_v_self->_csettings == NULL) != 0); + if (unlikely(__pyx_t_1)) { + + /* "httptools/parser/parser.pyx":53 + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) + * if self._csettings is NULL: + * raise MemoryError() # <<<<<<<<<<<<<< + * + * def __dealloc__(self): + */ + PyErr_NoMemory(); __PYX_ERR(0, 53, __pyx_L1_error) + + /* "httptools/parser/parser.pyx":52 + * self._csettings = \ + * PyMem_Malloc(sizeof(cparser.llhttp_settings_t)) + * if self._csettings is NULL: # <<<<<<<<<<<<<< + * raise MemoryError() + * + */ + } + + /* "httptools/parser/parser.pyx":44 + * Py_buffer py_buf + * + * def __cinit__(self): # <<<<<<<<<<<<<< + * self._cparser = \ + * PyMem_Malloc(sizeof(cparser.llhttp_t)) + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_AddTraceback("httptools.parser.parser.HttpParser.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":55 + * raise MemoryError() + * + * def __dealloc__(self): # <<<<<<<<<<<<<< + * PyMem_Free(self._cparser) + * PyMem_Free(self._csettings) + */ + +/* Python wrapper */ +static void __pyx_pw_9httptools_6parser_6parser_10HttpParser_3__dealloc__(PyObject *__pyx_v_self); /*proto*/ +static void __pyx_pw_9httptools_6parser_6parser_10HttpParser_3__dealloc__(PyObject *__pyx_v_self) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0); + __pyx_pf_9httptools_6parser_6parser_10HttpParser_2__dealloc__(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +static void __pyx_pf_9httptools_6parser_6parser_10HttpParser_2__dealloc__(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__dealloc__", 0); + + /* "httptools/parser/parser.pyx":56 + * + * def __dealloc__(self): + * PyMem_Free(self._cparser) # <<<<<<<<<<<<<< + * PyMem_Free(self._csettings) + * + */ + PyMem_Free(__pyx_v_self->_cparser); + + /* "httptools/parser/parser.pyx":57 + * def __dealloc__(self): + * PyMem_Free(self._cparser) + * PyMem_Free(self._csettings) # <<<<<<<<<<<<<< + * + * cdef _init(self, protocol, cparser.llhttp_type_t mode): + */ + PyMem_Free(__pyx_v_self->_csettings); + + /* "httptools/parser/parser.pyx":55 + * raise MemoryError() + * + * def __dealloc__(self): # <<<<<<<<<<<<<< + * PyMem_Free(self._cparser) + * PyMem_Free(self._csettings) + */ + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +/* "httptools/parser/parser.pyx":59 + * PyMem_Free(self._csettings) + * + * cdef _init(self, protocol, cparser.llhttp_type_t mode): # <<<<<<<<<<<<<< + * cparser.llhttp_settings_init(self._csettings) + * + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__init(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_protocol, llhttp_type_t __pyx_v_mode) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_init", 0); + + /* "httptools/parser/parser.pyx":60 + * + * cdef _init(self, protocol, cparser.llhttp_type_t mode): + * cparser.llhttp_settings_init(self._csettings) # <<<<<<<<<<<<<< + * + * cparser.llhttp_init(self._cparser, mode, self._csettings) + */ + llhttp_settings_init(__pyx_v_self->_csettings); + + /* "httptools/parser/parser.pyx":62 + * cparser.llhttp_settings_init(self._csettings) + * + * cparser.llhttp_init(self._cparser, mode, self._csettings) # <<<<<<<<<<<<<< + * self._cparser.data = self + * + */ + llhttp_init(__pyx_v_self->_cparser, __pyx_v_mode, __pyx_v_self->_csettings); + + /* "httptools/parser/parser.pyx":63 + * + * cparser.llhttp_init(self._cparser, mode, self._csettings) + * self._cparser.data = self # <<<<<<<<<<<<<< + * + * self._current_header_name = None + */ + __pyx_v_self->_cparser->data = ((void *)__pyx_v_self); + + /* "httptools/parser/parser.pyx":65 + * self._cparser.data = self + * + * self._current_header_name = None # <<<<<<<<<<<<<< + * self._current_header_value = None + * + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_current_header_name); + __Pyx_DECREF(__pyx_v_self->_current_header_name); + __pyx_v_self->_current_header_name = ((PyObject*)Py_None); + + /* "httptools/parser/parser.pyx":66 + * + * self._current_header_name = None + * self._current_header_value = None # <<<<<<<<<<<<<< + * + * self._proto_on_header = getattr(protocol, 'on_header', None) + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_current_header_value); + __Pyx_DECREF(__pyx_v_self->_current_header_value); + __pyx_v_self->_current_header_value = ((PyObject*)Py_None); + + /* "httptools/parser/parser.pyx":68 + * 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 + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_header, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_proto_on_header); + __Pyx_DECREF(__pyx_v_self->_proto_on_header); + __pyx_v_self->_proto_on_header = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":69 + * + * 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 + */ + __pyx_t_2 = (__pyx_v_self->_proto_on_header != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":70 + * 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( + */ + __pyx_v_self->_csettings->on_header_field = __pyx_f_9httptools_6parser_6parser_cb_on_header_field; + + /* "httptools/parser/parser.pyx":71 + * 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) + */ + __pyx_v_self->_csettings->on_header_value = __pyx_f_9httptools_6parser_6parser_cb_on_header_value; + + /* "httptools/parser/parser.pyx":69 + * + * 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 + */ + } + + /* "httptools/parser/parser.pyx":72 + * 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 + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_headers_complete, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 72, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_proto_on_headers_complete); + __Pyx_DECREF(__pyx_v_self->_proto_on_headers_complete); + __pyx_v_self->_proto_on_headers_complete = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":74 + * 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) + */ + __pyx_v_self->_csettings->on_headers_complete = __pyx_f_9httptools_6parser_6parser_cb_on_headers_complete; + + /* "httptools/parser/parser.pyx":76 + * 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 + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_body, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 76, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_proto_on_body); + __Pyx_DECREF(__pyx_v_self->_proto_on_body); + __pyx_v_self->_proto_on_body = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":77 + * + * self._proto_on_body = getattr(protocol, 'on_body', None) + * if self._proto_on_body is not None: # <<<<<<<<<<<<<< + * self._csettings.on_body = cb_on_body + * + */ + __pyx_t_3 = (__pyx_v_self->_proto_on_body != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "httptools/parser/parser.pyx":78 + * 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( + */ + __pyx_v_self->_csettings->on_body = __pyx_f_9httptools_6parser_6parser_cb_on_body; + + /* "httptools/parser/parser.pyx":77 + * + * self._proto_on_body = getattr(protocol, 'on_body', None) + * if self._proto_on_body is not None: # <<<<<<<<<<<<<< + * self._csettings.on_body = cb_on_body + * + */ + } + + /* "httptools/parser/parser.pyx":80 + * 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: + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_message_begin, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 80, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_proto_on_message_begin); + __Pyx_DECREF(__pyx_v_self->_proto_on_message_begin); + __pyx_v_self->_proto_on_message_begin = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":82 + * 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 + * + */ + __pyx_t_2 = (__pyx_v_self->_proto_on_message_begin != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":83 + * 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( + */ + __pyx_v_self->_csettings->on_message_begin = __pyx_f_9httptools_6parser_6parser_cb_on_message_begin; + + /* "httptools/parser/parser.pyx":82 + * 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 + * + */ + } + + /* "httptools/parser/parser.pyx":85 + * 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: + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_message_complete, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 85, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_proto_on_message_complete); + __Pyx_DECREF(__pyx_v_self->_proto_on_message_complete); + __pyx_v_self->_proto_on_message_complete = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":87 + * 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 + * + */ + __pyx_t_3 = (__pyx_v_self->_proto_on_message_complete != Py_None); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "httptools/parser/parser.pyx":88 + * 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( + */ + __pyx_v_self->_csettings->on_message_complete = __pyx_f_9httptools_6parser_6parser_cb_on_message_complete; + + /* "httptools/parser/parser.pyx":87 + * 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 + * + */ + } + + /* "httptools/parser/parser.pyx":90 + * 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 + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_chunk_header, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 90, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_proto_on_chunk_header); + __Pyx_DECREF(__pyx_v_self->_proto_on_chunk_header); + __pyx_v_self->_proto_on_chunk_header = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":92 + * 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( + */ + __pyx_v_self->_csettings->on_chunk_header = __pyx_f_9httptools_6parser_6parser_cb_on_chunk_header; + + /* "httptools/parser/parser.pyx":94 + * 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 + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_chunk_complete, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 94, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_proto_on_chunk_complete); + __Pyx_DECREF(__pyx_v_self->_proto_on_chunk_complete); + __pyx_v_self->_proto_on_chunk_complete = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":96 + * self._proto_on_chunk_complete = getattr( + * protocol, 'on_chunk_complete', None) + * self._csettings.on_chunk_complete = cb_on_chunk_complete # <<<<<<<<<<<<<< + * + * self._last_error = None + */ + __pyx_v_self->_csettings->on_chunk_complete = __pyx_f_9httptools_6parser_6parser_cb_on_chunk_complete; + + /* "httptools/parser/parser.pyx":98 + * self._csettings.on_chunk_complete = cb_on_chunk_complete + * + * self._last_error = None # <<<<<<<<<<<<<< + * + * cdef _maybe_call_on_header(self): + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_last_error); + __Pyx_DECREF(__pyx_v_self->_last_error); + __pyx_v_self->_last_error = Py_None; + + /* "httptools/parser/parser.pyx":59 + * PyMem_Free(self._csettings) + * + * cdef _init(self, protocol, cparser.llhttp_type_t mode): # <<<<<<<<<<<<<< + * cparser.llhttp_settings_init(self._csettings) + * + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser._init", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":100 + * 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 + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__maybe_call_on_header(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + PyObject *__pyx_v_current_header_name = NULL; + PyObject *__pyx_v_current_header_value = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_maybe_call_on_header", 0); + + /* "httptools/parser/parser.pyx":101 + * + * 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 + */ + __pyx_t_1 = (__pyx_v_self->_current_header_value != ((PyObject*)Py_None)); + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "httptools/parser/parser.pyx":102 + * 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 + * + */ + __pyx_t_3 = __pyx_v_self->_current_header_name; + __Pyx_INCREF(__pyx_t_3); + __pyx_v_current_header_name = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "httptools/parser/parser.pyx":103 + * 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 + */ + __pyx_t_3 = __pyx_v_self->_current_header_value; + __Pyx_INCREF(__pyx_t_3); + __pyx_v_current_header_value = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "httptools/parser/parser.pyx":105 + * current_header_value = self._current_header_value + * + * self._current_header_name = self._current_header_value = None # <<<<<<<<<<<<<< + * + * if self._proto_on_header is not None: + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_current_header_name); + __Pyx_DECREF(__pyx_v_self->_current_header_name); + __pyx_v_self->_current_header_name = ((PyObject*)Py_None); + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_current_header_value); + __Pyx_DECREF(__pyx_v_self->_current_header_value); + __pyx_v_self->_current_header_value = ((PyObject*)Py_None); + + /* "httptools/parser/parser.pyx":107 + * 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) + */ + __pyx_t_2 = (__pyx_v_self->_proto_on_header != Py_None); + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "httptools/parser/parser.pyx":109 + * 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): + */ + __Pyx_INCREF(__pyx_v_self->_proto_on_header); + __pyx_t_4 = __pyx_v_self->_proto_on_header; __pyx_t_5 = NULL; + __pyx_t_6 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + __pyx_t_6 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_current_header_name, __pyx_v_current_header_value}; + __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 108, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_3); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_current_header_name, __pyx_v_current_header_value}; + __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 108, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_3); + } else + #endif + { + __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 108, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_INCREF(__pyx_v_current_header_name); + __Pyx_GIVEREF(__pyx_v_current_header_name); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_v_current_header_name); + __Pyx_INCREF(__pyx_v_current_header_value); + __Pyx_GIVEREF(__pyx_v_current_header_value); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_v_current_header_value); + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 108, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "httptools/parser/parser.pyx":107 + * 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) + */ + } + + /* "httptools/parser/parser.pyx":101 + * + * 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 + */ + } + + /* "httptools/parser/parser.pyx":100 + * 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 + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser._maybe_call_on_header", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_current_header_name); + __Pyx_XDECREF(__pyx_v_current_header_value); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":111 + * current_header_value) + * + * cdef _on_header_field(self, bytes field): # <<<<<<<<<<<<<< + * self._maybe_call_on_header() + * if self._current_header_name is None: + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_header_field(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_field) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_on_header_field", 0); + + /* "httptools/parser/parser.pyx":112 + * + * cdef _on_header_field(self, bytes field): + * self._maybe_call_on_header() # <<<<<<<<<<<<<< + * if self._current_header_name is None: + * self._current_header_name = field + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_maybe_call_on_header(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 112, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":113 + * 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: + */ + __pyx_t_2 = (__pyx_v_self->_current_header_name == ((PyObject*)Py_None)); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":114 + * self._maybe_call_on_header() + * if self._current_header_name is None: + * self._current_header_name = field # <<<<<<<<<<<<<< + * else: + * self._current_header_name += field + */ + __Pyx_INCREF(__pyx_v_field); + __Pyx_GIVEREF(__pyx_v_field); + __Pyx_GOTREF(__pyx_v_self->_current_header_name); + __Pyx_DECREF(__pyx_v_self->_current_header_name); + __pyx_v_self->_current_header_name = __pyx_v_field; + + /* "httptools/parser/parser.pyx":113 + * 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: + */ + goto __pyx_L3; + } + + /* "httptools/parser/parser.pyx":116 + * self._current_header_name = field + * else: + * self._current_header_name += field # <<<<<<<<<<<<<< + * + * cdef _on_header_value(self, bytes val): + */ + /*else*/ { + __pyx_t_1 = PyNumber_InPlaceAdd(__pyx_v_self->_current_header_name, __pyx_v_field); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 116, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->_current_header_name); + __Pyx_DECREF(__pyx_v_self->_current_header_name); + __pyx_v_self->_current_header_name = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + } + __pyx_L3:; + + /* "httptools/parser/parser.pyx":111 + * current_header_value) + * + * cdef _on_header_field(self, bytes field): # <<<<<<<<<<<<<< + * self._maybe_call_on_header() + * if self._current_header_name is None: + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser._on_header_field", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":118 + * self._current_header_name += field + * + * cdef _on_header_value(self, bytes val): # <<<<<<<<<<<<<< + * if self._current_header_value is None: + * self._current_header_value = val + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_header_value(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_val) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_on_header_value", 0); + + /* "httptools/parser/parser.pyx":119 + * + * cdef _on_header_value(self, bytes val): + * if self._current_header_value is None: # <<<<<<<<<<<<<< + * self._current_header_value = val + * else: + */ + __pyx_t_1 = (__pyx_v_self->_current_header_value == ((PyObject*)Py_None)); + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "httptools/parser/parser.pyx":120 + * 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 + */ + __Pyx_INCREF(__pyx_v_val); + __Pyx_GIVEREF(__pyx_v_val); + __Pyx_GOTREF(__pyx_v_self->_current_header_value); + __Pyx_DECREF(__pyx_v_self->_current_header_value); + __pyx_v_self->_current_header_value = __pyx_v_val; + + /* "httptools/parser/parser.pyx":119 + * + * cdef _on_header_value(self, bytes val): + * if self._current_header_value is None: # <<<<<<<<<<<<<< + * self._current_header_value = val + * else: + */ + goto __pyx_L3; + } + + /* "httptools/parser/parser.pyx":123 + * else: + * # This is unlikely, as mostly HTTP headers are one-line + * self._current_header_value += val # <<<<<<<<<<<<<< + * + * cdef _on_headers_complete(self): + */ + /*else*/ { + __pyx_t_3 = PyNumber_InPlaceAdd(__pyx_v_self->_current_header_value, __pyx_v_val); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 123, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_3); + __Pyx_GOTREF(__pyx_v_self->_current_header_value); + __Pyx_DECREF(__pyx_v_self->_current_header_value); + __pyx_v_self->_current_header_value = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + } + __pyx_L3:; + + /* "httptools/parser/parser.pyx":118 + * self._current_header_name += field + * + * cdef _on_header_value(self, bytes val): # <<<<<<<<<<<<<< + * if self._current_header_value is None: + * self._current_header_value = val + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser._on_header_value", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":125 + * self._current_header_value += val + * + * cdef _on_headers_complete(self): # <<<<<<<<<<<<<< + * self._maybe_call_on_header() + * + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_headers_complete(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_on_headers_complete", 0); + + /* "httptools/parser/parser.pyx":126 + * + * cdef _on_headers_complete(self): + * self._maybe_call_on_header() # <<<<<<<<<<<<<< + * + * if self._proto_on_headers_complete is not None: + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_maybe_call_on_header(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":128 + * self._maybe_call_on_header() + * + * if self._proto_on_headers_complete is not None: # <<<<<<<<<<<<<< + * self._proto_on_headers_complete() + * + */ + __pyx_t_2 = (__pyx_v_self->_proto_on_headers_complete != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":129 + * + * if self._proto_on_headers_complete is not None: + * self._proto_on_headers_complete() # <<<<<<<<<<<<<< + * + * cdef _on_chunk_header(self): + */ + __Pyx_INCREF(__pyx_v_self->_proto_on_headers_complete); + __pyx_t_4 = __pyx_v_self->_proto_on_headers_complete; __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 129, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":128 + * self._maybe_call_on_header() + * + * if self._proto_on_headers_complete is not None: # <<<<<<<<<<<<<< + * self._proto_on_headers_complete() + * + */ + } + + /* "httptools/parser/parser.pyx":125 + * self._current_header_value += val + * + * cdef _on_headers_complete(self): # <<<<<<<<<<<<<< + * self._maybe_call_on_header() + * + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser._on_headers_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":131 + * 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): + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_chunk_header(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_on_chunk_header", 0); + + /* "httptools/parser/parser.pyx":132 + * + * 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') + */ + __pyx_t_2 = (__pyx_v_self->_current_header_value != ((PyObject*)Py_None)); + __pyx_t_3 = (__pyx_t_2 != 0); + if (!__pyx_t_3) { + } else { + __pyx_t_1 = __pyx_t_3; + goto __pyx_L4_bool_binop_done; + } + + /* "httptools/parser/parser.pyx":133 + * 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') + * + */ + __pyx_t_3 = (__pyx_v_self->_current_header_name != ((PyObject*)Py_None)); + __pyx_t_2 = (__pyx_t_3 != 0); + __pyx_t_1 = __pyx_t_2; + __pyx_L4_bool_binop_done:; + + /* "httptools/parser/parser.pyx":132 + * + * 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 (unlikely(__pyx_t_1)) { + + /* "httptools/parser/parser.pyx":134 + * 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: + */ + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_HttpParserError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 134, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_kp_u_invalid_headers_state) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_kp_u_invalid_headers_state); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 134, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(0, 134, __pyx_L1_error) + + /* "httptools/parser/parser.pyx":132 + * + * 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') + */ + } + + /* "httptools/parser/parser.pyx":136 + * raise HttpParserError('invalid headers state') + * + * if self._proto_on_chunk_header is not None: # <<<<<<<<<<<<<< + * self._proto_on_chunk_header() + * + */ + __pyx_t_1 = (__pyx_v_self->_proto_on_chunk_header != Py_None); + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "httptools/parser/parser.pyx":137 + * + * if self._proto_on_chunk_header is not None: + * self._proto_on_chunk_header() # <<<<<<<<<<<<<< + * + * cdef _on_chunk_complete(self): + */ + __Pyx_INCREF(__pyx_v_self->_proto_on_chunk_header); + __pyx_t_5 = __pyx_v_self->_proto_on_chunk_header; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallNoArg(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 137, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "httptools/parser/parser.pyx":136 + * raise HttpParserError('invalid headers state') + * + * if self._proto_on_chunk_header is not None: # <<<<<<<<<<<<<< + * self._proto_on_chunk_header() + * + */ + } + + /* "httptools/parser/parser.pyx":131 + * 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): + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser._on_chunk_header", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":139 + * self._proto_on_chunk_header() + * + * cdef _on_chunk_complete(self): # <<<<<<<<<<<<<< + * self._maybe_call_on_header() + * + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_10HttpParser__on_chunk_complete(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_on_chunk_complete", 0); + + /* "httptools/parser/parser.pyx":140 + * + * cdef _on_chunk_complete(self): + * self._maybe_call_on_header() # <<<<<<<<<<<<<< + * + * if self._proto_on_chunk_complete is not None: + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_self->__pyx_vtab)->_maybe_call_on_header(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 140, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":142 + * self._maybe_call_on_header() + * + * if self._proto_on_chunk_complete is not None: # <<<<<<<<<<<<<< + * self._proto_on_chunk_complete() + * + */ + __pyx_t_2 = (__pyx_v_self->_proto_on_chunk_complete != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":143 + * + * if self._proto_on_chunk_complete is not None: + * self._proto_on_chunk_complete() # <<<<<<<<<<<<<< + * + * ### Public API ### + */ + __Pyx_INCREF(__pyx_v_self->_proto_on_chunk_complete); + __pyx_t_4 = __pyx_v_self->_proto_on_chunk_complete; __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":142 + * self._maybe_call_on_header() + * + * if self._proto_on_chunk_complete is not None: # <<<<<<<<<<<<<< + * self._proto_on_chunk_complete() + * + */ + } + + /* "httptools/parser/parser.pyx":139 + * self._proto_on_chunk_header() + * + * cdef _on_chunk_complete(self): # <<<<<<<<<<<<<< + * self._maybe_call_on_header() + * + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser._on_chunk_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":147 + * ### Public API ### + * + * def get_http_version(self): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_t* parser = self._cparser + * return '{}.{}'.format(parser.http_major, parser.http_minor) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_5get_http_version(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_5get_http_version(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_http_version (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_10HttpParser_4get_http_version(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_4get_http_version(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + llhttp_t *__pyx_v_parser; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + llhttp_t *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_http_version", 0); + + /* "httptools/parser/parser.pyx":148 + * + * def get_http_version(self): + * cdef cparser.llhttp_t* parser = self._cparser # <<<<<<<<<<<<<< + * return '{}.{}'.format(parser.http_major, parser.http_minor) + * + */ + __pyx_t_1 = __pyx_v_self->_cparser; + __pyx_v_parser = __pyx_t_1; + + /* "httptools/parser/parser.pyx":149 + * 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): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_, __pyx_n_s_format); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 149, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = __Pyx_PyInt_From_uint8_t(__pyx_v_parser->http_major); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 149, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyInt_From_uint8_t(__pyx_v_parser->http_minor); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 149, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = NULL; + __pyx_t_7 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_7 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, __pyx_t_5}; + __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 149, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, __pyx_t_5}; + __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 149, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } else + #endif + { + __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 149, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_6) { + __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL; + } + __Pyx_GIVEREF(__pyx_t_4); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_4); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_5); + __pyx_t_4 = 0; + __pyx_t_5 = 0; + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 149, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "httptools/parser/parser.pyx":147 + * ### Public API ### + * + * def get_http_version(self): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_t* parser = self._cparser + * return '{}.{}'.format(parser.http_major, parser.http_minor) + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser.get_http_version", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":151 + * return '{}.{}'.format(parser.http_major, parser.http_minor) + * + * def should_keep_alive(self): # <<<<<<<<<<<<<< + * return bool(cparser.llhttp_should_keep_alive(self._cparser)) + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_7should_keep_alive(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_7should_keep_alive(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("should_keep_alive (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_10HttpParser_6should_keep_alive(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_6should_keep_alive(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("should_keep_alive", 0); + + /* "httptools/parser/parser.pyx":152 + * + * def should_keep_alive(self): + * return bool(cparser.llhttp_should_keep_alive(self._cparser)) # <<<<<<<<<<<<<< + * + * def should_upgrade(self): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyInt_From_int(llhttp_should_keep_alive(__pyx_v_self->_cparser)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 152, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 152, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyBool_FromLong((!(!__pyx_t_2))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 152, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "httptools/parser/parser.pyx":151 + * return '{}.{}'.format(parser.http_major, parser.http_minor) + * + * def should_keep_alive(self): # <<<<<<<<<<<<<< + * return bool(cparser.llhttp_should_keep_alive(self._cparser)) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser.should_keep_alive", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":154 + * return bool(cparser.llhttp_should_keep_alive(self._cparser)) + * + * def should_upgrade(self): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_t* parser = self._cparser + * return bool(parser.upgrade) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_9should_upgrade(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_9should_upgrade(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("should_upgrade (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_10HttpParser_8should_upgrade(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_8should_upgrade(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + llhttp_t *__pyx_v_parser; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + llhttp_t *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_t_3; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("should_upgrade", 0); + + /* "httptools/parser/parser.pyx":155 + * + * def should_upgrade(self): + * cdef cparser.llhttp_t* parser = self._cparser # <<<<<<<<<<<<<< + * return bool(parser.upgrade) + * + */ + __pyx_t_1 = __pyx_v_self->_cparser; + __pyx_v_parser = __pyx_t_1; + + /* "httptools/parser/parser.pyx":156 + * def should_upgrade(self): + * cdef cparser.llhttp_t* parser = self._cparser + * return bool(parser.upgrade) # <<<<<<<<<<<<<< + * + * def feed_data(self, data): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __Pyx_PyInt_From_uint8_t(__pyx_v_parser->upgrade); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 156, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 156, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyBool_FromLong((!(!__pyx_t_3))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 156, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "httptools/parser/parser.pyx":154 + * return bool(cparser.llhttp_should_keep_alive(self._cparser)) + * + * def should_upgrade(self): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_t* parser = self._cparser + * return bool(parser.upgrade) + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser.should_upgrade", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":158 + * return bool(parser.upgrade) + * + * def feed_data(self, data): # <<<<<<<<<<<<<< + * cdef: + * size_t data_len + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_11feed_data(PyObject *__pyx_v_self, PyObject *__pyx_v_data); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_11feed_data(PyObject *__pyx_v_self, PyObject *__pyx_v_data) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("feed_data (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_10HttpParser_10feed_data(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self), ((PyObject *)__pyx_v_data)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_10feed_data(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, PyObject *__pyx_v_data) { + size_t __pyx_v_data_len; + llhttp_errno_t __pyx_v_err; + Py_buffer *__pyx_v_buf; + int __pyx_v_owning_buf; + char *__pyx_v_err_pos; + PyObject *__pyx_v_ex = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + char const *__pyx_t_9; + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("feed_data", 0); + + /* "httptools/parser/parser.pyx":163 + * cparser.llhttp_errno_t err + * Py_buffer *buf + * bint owning_buf = False # <<<<<<<<<<<<<< + * char* err_pos + * + */ + __pyx_v_owning_buf = 0; + + /* "httptools/parser/parser.pyx":166 + * char* err_pos + * + * if PyMemoryView_Check(data): # <<<<<<<<<<<<<< + * buf = PyMemoryView_GET_BUFFER(data) + * data_len = buf.len + */ + __pyx_t_1 = (PyMemoryView_Check(__pyx_v_data) != 0); + if (__pyx_t_1) { + + /* "httptools/parser/parser.pyx":167 + * + * if PyMemoryView_Check(data): + * buf = PyMemoryView_GET_BUFFER(data) # <<<<<<<<<<<<<< + * data_len = buf.len + * err = cparser.llhttp_execute( + */ + __pyx_v_buf = PyMemoryView_GET_BUFFER(__pyx_v_data); + + /* "httptools/parser/parser.pyx":168 + * if PyMemoryView_Check(data): + * buf = PyMemoryView_GET_BUFFER(data) + * data_len = buf.len # <<<<<<<<<<<<<< + * err = cparser.llhttp_execute( + * self._cparser, + */ + __pyx_v_data_len = ((size_t)__pyx_v_buf->len); + + /* "httptools/parser/parser.pyx":169 + * buf = PyMemoryView_GET_BUFFER(data) + * data_len = buf.len + * err = cparser.llhttp_execute( # <<<<<<<<<<<<<< + * self._cparser, + * buf.buf, + */ + __pyx_v_err = llhttp_execute(__pyx_v_self->_cparser, ((char *)__pyx_v_buf->buf), __pyx_v_data_len); + + /* "httptools/parser/parser.pyx":166 + * char* err_pos + * + * if PyMemoryView_Check(data): # <<<<<<<<<<<<<< + * buf = PyMemoryView_GET_BUFFER(data) + * data_len = buf.len + */ + goto __pyx_L3; + } + + /* "httptools/parser/parser.pyx":175 + * + * else: + * buf = &self.py_buf # <<<<<<<<<<<<<< + * PyObject_GetBuffer(data, buf, PyBUF_SIMPLE) + * owning_buf = True + */ + /*else*/ { + __pyx_v_buf = (&__pyx_v_self->py_buf); + + /* "httptools/parser/parser.pyx":176 + * else: + * buf = &self.py_buf + * PyObject_GetBuffer(data, buf, PyBUF_SIMPLE) # <<<<<<<<<<<<<< + * owning_buf = True + * data_len = buf.len + */ + __pyx_t_2 = PyObject_GetBuffer(__pyx_v_data, __pyx_v_buf, PyBUF_SIMPLE); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 176, __pyx_L1_error) + + /* "httptools/parser/parser.pyx":177 + * buf = &self.py_buf + * PyObject_GetBuffer(data, buf, PyBUF_SIMPLE) + * owning_buf = True # <<<<<<<<<<<<<< + * data_len = buf.len + * + */ + __pyx_v_owning_buf = 1; + + /* "httptools/parser/parser.pyx":178 + * PyObject_GetBuffer(data, buf, PyBUF_SIMPLE) + * owning_buf = True + * data_len = buf.len # <<<<<<<<<<<<<< + * + * err = cparser.llhttp_execute( + */ + __pyx_v_data_len = ((size_t)__pyx_v_buf->len); + + /* "httptools/parser/parser.pyx":180 + * data_len = buf.len + * + * err = cparser.llhttp_execute( # <<<<<<<<<<<<<< + * self._cparser, + * buf.buf, + */ + __pyx_v_err = llhttp_execute(__pyx_v_self->_cparser, ((char *)__pyx_v_buf->buf), __pyx_v_data_len); + } + __pyx_L3:; + + /* "httptools/parser/parser.pyx":185 + * data_len) + * + * try: # <<<<<<<<<<<<<< + * if self._cparser.upgrade == 1 and err == cparser.HPE_PAUSED_UPGRADE: + * err_pos = cparser.llhttp_get_error_pos(self._cparser) + */ + /*try:*/ { + + /* "httptools/parser/parser.pyx":186 + * + * try: + * if self._cparser.upgrade == 1 and err == cparser.HPE_PAUSED_UPGRADE: # <<<<<<<<<<<<<< + * err_pos = cparser.llhttp_get_error_pos(self._cparser) + * + */ + __pyx_t_3 = ((__pyx_v_self->_cparser->upgrade == 1) != 0); + if (__pyx_t_3) { + } else { + __pyx_t_1 = __pyx_t_3; + goto __pyx_L8_bool_binop_done; + } + __pyx_t_3 = ((__pyx_v_err == HPE_PAUSED_UPGRADE) != 0); + __pyx_t_1 = __pyx_t_3; + __pyx_L8_bool_binop_done:; + if (unlikely(__pyx_t_1)) { + + /* "httptools/parser/parser.pyx":187 + * 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 + */ + __pyx_v_err_pos = llhttp_get_error_pos(__pyx_v_self->_cparser); + + /* "httptools/parser/parser.pyx":193 + * # 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 + */ + llhttp_resume_after_upgrade(__pyx_v_self->_cparser); + + /* "httptools/parser/parser.pyx":199 + * # 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: + */ + __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_HttpParserUpgrade); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 199, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = __Pyx_PyInt_From_ptrdiff_t((__pyx_v_err_pos - ((char *)__pyx_v_buf->buf))); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 199, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 199, __pyx_L5_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(0, 199, __pyx_L5_error) + + /* "httptools/parser/parser.pyx":186 + * + * try: + * if self._cparser.upgrade == 1 and err == cparser.HPE_PAUSED_UPGRADE: # <<<<<<<<<<<<<< + * err_pos = cparser.llhttp_get_error_pos(self._cparser) + * + */ + } + } + + /* "httptools/parser/parser.pyx":201 + * raise HttpParserUpgrade(err_pos - buf.buf) + * finally: + * if owning_buf: # <<<<<<<<<<<<<< + * PyBuffer_Release(buf) + * + */ + /*finally:*/ { + /*normal exit:*/{ + __pyx_t_1 = (__pyx_v_owning_buf != 0); + if (__pyx_t_1) { + + /* "httptools/parser/parser.pyx":202 + * finally: + * if owning_buf: + * PyBuffer_Release(buf) # <<<<<<<<<<<<<< + * + * if err != cparser.HPE_OK: + */ + PyBuffer_Release(__pyx_v_buf); + + /* "httptools/parser/parser.pyx":201 + * raise HttpParserUpgrade(err_pos - buf.buf) + * finally: + * if owning_buf: # <<<<<<<<<<<<<< + * PyBuffer_Release(buf) + * + */ + } + goto __pyx_L6; + } + __pyx_L5_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_10); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_13); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __pyx_t_2 = __pyx_lineno; __pyx_t_8 = __pyx_clineno; __pyx_t_9 = __pyx_filename; + { + __pyx_t_1 = (__pyx_v_owning_buf != 0); + if (__pyx_t_1) { + + /* "httptools/parser/parser.pyx":202 + * finally: + * if owning_buf: + * PyBuffer_Release(buf) # <<<<<<<<<<<<<< + * + * if err != cparser.HPE_OK: + */ + PyBuffer_Release(__pyx_v_buf); + + /* "httptools/parser/parser.pyx":201 + * raise HttpParserUpgrade(err_pos - buf.buf) + * finally: + * if owning_buf: # <<<<<<<<<<<<<< + * PyBuffer_Release(buf) + * + */ + } + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_13); + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15); + } + __Pyx_XGIVEREF(__pyx_t_10); + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12); + __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; + __pyx_lineno = __pyx_t_2; __pyx_clineno = __pyx_t_8; __pyx_filename = __pyx_t_9; + goto __pyx_L1_error; + } + __pyx_L6:; + } + + /* "httptools/parser/parser.pyx":204 + * PyBuffer_Release(buf) + * + * if err != cparser.HPE_OK: # <<<<<<<<<<<<<< + * ex = parser_error_from_errno( + * self._cparser, + */ + __pyx_t_1 = ((__pyx_v_err != HPE_OK) != 0); + if (__pyx_t_1) { + + /* "httptools/parser/parser.pyx":205 + * + * if err != cparser.HPE_OK: + * ex = parser_error_from_errno( # <<<<<<<<<<<<<< + * self._cparser, + * self._cparser.error) + */ + __pyx_t_4 = __pyx_f_9httptools_6parser_6parser_parser_error_from_errno(__pyx_v_self->_cparser, ((llhttp_errno_t)__pyx_v_self->_cparser->error)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 205, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_v_ex = __pyx_t_4; + __pyx_t_4 = 0; + + /* "httptools/parser/parser.pyx":208 + * self._cparser, + * self._cparser.error) + * if isinstance(ex, HttpParserCallbackError): # <<<<<<<<<<<<<< + * if self._last_error is not None: + * ex.__context__ = self._last_error + */ + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_HttpParserCallbackError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 208, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_1 = PyObject_IsInstance(__pyx_v_ex, __pyx_t_4); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(0, 208, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_3 = (__pyx_t_1 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":209 + * self._cparser.error) + * if isinstance(ex, HttpParserCallbackError): + * if self._last_error is not None: # <<<<<<<<<<<<<< + * ex.__context__ = self._last_error + * self._last_error = None + */ + __pyx_t_3 = (__pyx_v_self->_last_error != Py_None); + __pyx_t_1 = (__pyx_t_3 != 0); + if (__pyx_t_1) { + + /* "httptools/parser/parser.pyx":210 + * if isinstance(ex, HttpParserCallbackError): + * if self._last_error is not None: + * ex.__context__ = self._last_error # <<<<<<<<<<<<<< + * self._last_error = None + * raise ex + */ + __pyx_t_4 = __pyx_v_self->_last_error; + __Pyx_INCREF(__pyx_t_4); + if (__Pyx_PyObject_SetAttrStr(__pyx_v_ex, __pyx_n_s_context, __pyx_t_4) < 0) __PYX_ERR(0, 210, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "httptools/parser/parser.pyx":211 + * if self._last_error is not None: + * ex.__context__ = self._last_error + * self._last_error = None # <<<<<<<<<<<<<< + * raise ex + * + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_self->_last_error); + __Pyx_DECREF(__pyx_v_self->_last_error); + __pyx_v_self->_last_error = Py_None; + + /* "httptools/parser/parser.pyx":209 + * self._cparser.error) + * if isinstance(ex, HttpParserCallbackError): + * if self._last_error is not None: # <<<<<<<<<<<<<< + * ex.__context__ = self._last_error + * self._last_error = None + */ + } + + /* "httptools/parser/parser.pyx":208 + * self._cparser, + * self._cparser.error) + * if isinstance(ex, HttpParserCallbackError): # <<<<<<<<<<<<<< + * if self._last_error is not None: + * ex.__context__ = self._last_error + */ + } + + /* "httptools/parser/parser.pyx":212 + * ex.__context__ = self._last_error + * self._last_error = None + * raise ex # <<<<<<<<<<<<<< + * + * + */ + __Pyx_Raise(__pyx_v_ex, 0, 0, 0); + __PYX_ERR(0, 212, __pyx_L1_error) + + /* "httptools/parser/parser.pyx":204 + * PyBuffer_Release(buf) + * + * if err != cparser.HPE_OK: # <<<<<<<<<<<<<< + * ex = parser_error_from_errno( + * self._cparser, + */ + } + + /* "httptools/parser/parser.pyx":158 + * return bool(parser.upgrade) + * + * def feed_data(self, data): # <<<<<<<<<<<<<< + * cdef: + * size_t data_len + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser.feed_data", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_13__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_13__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_10HttpParser_12__reduce_cython__(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_12__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(1, 2, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_15__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_10HttpParser_15__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_10HttpParser_14__setstate_cython__(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_10HttpParser_14__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(1, 4, __pyx_L1_error) + + /* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpParser.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":217 + * cdef class HttpRequestParser(HttpParser): + * + * def __init__(self, protocol): # <<<<<<<<<<<<<< + * self._init(protocol, cparser.HTTP_REQUEST) + * + */ + +/* Python wrapper */ +static int __pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_protocol = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_protocol,0}; + PyObject* values[1] = {0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_protocol)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 217, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + } + __pyx_v_protocol = values[0]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 217, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("httptools.parser.parser.HttpRequestParser.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_9httptools_6parser_6parser_17HttpRequestParser___init__(((struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *)__pyx_v_self), __pyx_v_protocol); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_9httptools_6parser_6parser_17HttpRequestParser___init__(struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self, PyObject *__pyx_v_protocol) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__init__", 0); + + /* "httptools/parser/parser.pyx":218 + * + * def __init__(self, protocol): + * self._init(protocol, cparser.HTTP_REQUEST) # <<<<<<<<<<<<<< + * + * self._proto_on_url = getattr(protocol, 'on_url', None) + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpRequestParser *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base._init(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self), __pyx_v_protocol, HTTP_REQUEST); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 218, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":220 + * 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 + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_url, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 220, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->__pyx_base._proto_on_url); + __Pyx_DECREF(__pyx_v_self->__pyx_base._proto_on_url); + __pyx_v_self->__pyx_base._proto_on_url = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":221 + * + * self._proto_on_url = getattr(protocol, 'on_url', None) + * if self._proto_on_url is not None: # <<<<<<<<<<<<<< + * self._csettings.on_url = cb_on_url + * + */ + __pyx_t_2 = (__pyx_v_self->__pyx_base._proto_on_url != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":222 + * 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): + */ + __pyx_v_self->__pyx_base._csettings->on_url = __pyx_f_9httptools_6parser_6parser_cb_on_url; + + /* "httptools/parser/parser.pyx":221 + * + * self._proto_on_url = getattr(protocol, 'on_url', None) + * if self._proto_on_url is not None: # <<<<<<<<<<<<<< + * self._csettings.on_url = cb_on_url + * + */ + } + + /* "httptools/parser/parser.pyx":217 + * cdef class HttpRequestParser(HttpParser): + * + * def __init__(self, protocol): # <<<<<<<<<<<<<< + * self._init(protocol, cparser.HTTP_REQUEST) + * + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpRequestParser.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":224 + * 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) + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_3get_method(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_3get_method(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_method (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_2get_method(((struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_2get_method(struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self) { + llhttp_t *__pyx_v_parser; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + llhttp_t *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_method", 0); + + /* "httptools/parser/parser.pyx":225 + * + * def get_method(self): + * cdef cparser.llhttp_t* parser = self._cparser # <<<<<<<<<<<<<< + * return cparser.llhttp_method_name( parser.method) + * + */ + __pyx_t_1 = __pyx_v_self->__pyx_base._cparser; + __pyx_v_parser = __pyx_t_1; + + /* "httptools/parser/parser.pyx":226 + * def get_method(self): + * cdef cparser.llhttp_t* parser = self._cparser + * return cparser.llhttp_method_name( parser.method) # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __Pyx_PyBytes_FromString(llhttp_method_name(((llhttp_method_t)__pyx_v_parser->method))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 226, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "httptools/parser/parser.pyx":224 + * 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) + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("httptools.parser.parser.HttpRequestParser.get_method", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_4__reduce_cython__(((struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(1, 2, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpRequestParser.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_6__setstate_cython__(((struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_17HttpRequestParser_6__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(1, 4, __pyx_L1_error) + + /* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpRequestParser.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":231 + * cdef class HttpResponseParser(HttpParser): + * + * def __init__(self, protocol): # <<<<<<<<<<<<<< + * self._init(protocol, cparser.HTTP_RESPONSE) + * + */ + +/* Python wrapper */ +static int __pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_protocol = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_protocol,0}; + PyObject* values[1] = {0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_protocol)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 231, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + } + __pyx_v_protocol = values[0]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 231, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("httptools.parser.parser.HttpResponseParser.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_9httptools_6parser_6parser_18HttpResponseParser___init__(((struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *)__pyx_v_self), __pyx_v_protocol); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_9httptools_6parser_6parser_18HttpResponseParser___init__(struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self, PyObject *__pyx_v_protocol) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__init__", 0); + + /* "httptools/parser/parser.pyx":232 + * + * def __init__(self, protocol): + * self._init(protocol, cparser.HTTP_RESPONSE) # <<<<<<<<<<<<<< + * + * self._proto_on_status = getattr(protocol, 'on_status', None) + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpResponseParser *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base._init(((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_v_self), __pyx_v_protocol, HTTP_RESPONSE); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 232, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":234 + * 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 + */ + __pyx_t_1 = __Pyx_GetAttr3(__pyx_v_protocol, __pyx_n_u_on_status, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 234, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_v_self->__pyx_base._proto_on_status); + __Pyx_DECREF(__pyx_v_self->__pyx_base._proto_on_status); + __pyx_v_self->__pyx_base._proto_on_status = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":235 + * + * self._proto_on_status = getattr(protocol, 'on_status', None) + * if self._proto_on_status is not None: # <<<<<<<<<<<<<< + * self._csettings.on_status = cb_on_status + * + */ + __pyx_t_2 = (__pyx_v_self->__pyx_base._proto_on_status != Py_None); + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "httptools/parser/parser.pyx":236 + * 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): + */ + __pyx_v_self->__pyx_base._csettings->on_status = __pyx_f_9httptools_6parser_6parser_cb_on_status; + + /* "httptools/parser/parser.pyx":235 + * + * self._proto_on_status = getattr(protocol, 'on_status', None) + * if self._proto_on_status is not None: # <<<<<<<<<<<<<< + * self._csettings.on_status = cb_on_status + * + */ + } + + /* "httptools/parser/parser.pyx":231 + * cdef class HttpResponseParser(HttpParser): + * + * def __init__(self, protocol): # <<<<<<<<<<<<<< + * self._init(protocol, cparser.HTTP_RESPONSE) + * + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpResponseParser.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":238 + * self._csettings.on_status = cb_on_status + * + * def get_status_code(self): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_t* parser = self._cparser + * return parser.status_code + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_3get_status_code(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_3get_status_code(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("get_status_code (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_2get_status_code(((struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_2get_status_code(struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self) { + llhttp_t *__pyx_v_parser; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + llhttp_t *__pyx_t_1; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("get_status_code", 0); + + /* "httptools/parser/parser.pyx":239 + * + * def get_status_code(self): + * cdef cparser.llhttp_t* parser = self._cparser # <<<<<<<<<<<<<< + * return parser.status_code + * + */ + __pyx_t_1 = __pyx_v_self->__pyx_base._cparser; + __pyx_v_parser = __pyx_t_1; + + /* "httptools/parser/parser.pyx":240 + * def get_status_code(self): + * cdef cparser.llhttp_t* parser = self._cparser + * return parser.status_code # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __Pyx_PyInt_From_uint16_t(__pyx_v_parser->status_code); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 240, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; + goto __pyx_L0; + + /* "httptools/parser/parser.pyx":238 + * self._csettings.on_status = cb_on_status + * + * def get_status_code(self): # <<<<<<<<<<<<<< + * cdef cparser.llhttp_t* parser = self._cparser + * return parser.status_code + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("httptools.parser.parser.HttpResponseParser.get_status_code", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_4__reduce_cython__(((struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(1, 2, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpResponseParser.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_6__setstate_cython__(((struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_6parser_18HttpResponseParser_6__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(1, 4, __pyx_L1_error) + + /* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.parser.HttpResponseParser.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":243 + * + * + * cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_message_begin(llhttp_t *__pyx_v_parser) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_message_begin", 0); + + /* "httptools/parser/parser.pyx":244 + * + * cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: + * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< + * try: + * pyparser._proto_on_message_begin() + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":245 + * 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: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":246 + * cdef HttpParser pyparser = parser.data + * try: + * pyparser._proto_on_message_begin() # <<<<<<<<<<<<<< + * except BaseException as ex: + * pyparser._last_error = ex + */ + __Pyx_INCREF(__pyx_v_pyparser->_proto_on_message_begin); + __pyx_t_5 = __pyx_v_pyparser->_proto_on_message_begin; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallNoArg(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 246, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":245 + * 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: + */ + } + + /* "httptools/parser/parser.pyx":251 + * return -1 + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "httptools/parser/parser.pyx":247 + * try: + * pyparser._proto_on_message_begin() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + __pyx_t_7 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_7) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_message_begin", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_5, &__pyx_t_6) < 0) __PYX_ERR(0, 247, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(__pyx_t_5); + __pyx_v_ex = __pyx_t_5; + /*try:*/ { + + /* "httptools/parser/parser.pyx":248 + * pyparser._proto_on_message_begin() + * except BaseException as ex: + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return -1 + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":249 + * except BaseException as ex: + * pyparser._last_error = ex + * return -1 # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = -1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":247 + * try: + * pyparser._proto_on_message_begin() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_7 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_7; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":245 + * 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: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":243 + * + * + * cdef int cb_on_message_begin(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_message_begin", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":254 + * + * + * cdef int cb_on_url(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_url(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_url", 0); + + /* "httptools/parser/parser.pyx":256 + * 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]) + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":257 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_url(at[:length]) + * except BaseException as ex: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":258 + * 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") + */ + __pyx_t_5 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_at + 0, __pyx_v_length - 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 258, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_v_pyparser->_proto_on_url); + __pyx_t_6 = __pyx_v_pyparser->_proto_on_url; __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 258, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":257 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_url(at[:length]) + * except BaseException as ex: + */ + } + + /* "httptools/parser/parser.pyx":264 + * return cparser.HPE_USER + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "httptools/parser/parser.pyx":259 + * 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 + */ + __pyx_t_8 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_8) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_url", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_5) < 0) __PYX_ERR(0, 259, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __pyx_v_ex = __pyx_t_6; + /*try:*/ { + + /* "httptools/parser/parser.pyx":260 + * 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 + */ + llhttp_set_error_reason(__pyx_v_parser, ((char const *)"`on_url` callback error")); + + /* "httptools/parser/parser.pyx":261 + * except BaseException as ex: + * cparser.llhttp_set_error_reason(parser, "`on_url` callback error") + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return cparser.HPE_USER + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":262 + * cparser.llhttp_set_error_reason(parser, "`on_url` callback error") + * pyparser._last_error = ex + * return cparser.HPE_USER # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = HPE_USER; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":259 + * 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 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_8 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_8; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":257 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_url(at[:length]) + * except BaseException as ex: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":254 + * + * + * cdef int cb_on_url(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_url", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":267 + * + * + * cdef int cb_on_status(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_status(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_status", 0); + + /* "httptools/parser/parser.pyx":269 + * 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]) + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":270 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_status(at[:length]) + * except BaseException as ex: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":271 + * 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") + */ + __pyx_t_5 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_at + 0, __pyx_v_length - 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 271, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_v_pyparser->_proto_on_status); + __pyx_t_6 = __pyx_v_pyparser->_proto_on_status; __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 271, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":270 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_status(at[:length]) + * except BaseException as ex: + */ + } + + /* "httptools/parser/parser.pyx":277 + * return cparser.HPE_USER + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "httptools/parser/parser.pyx":272 + * 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 + */ + __pyx_t_8 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_8) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_status", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_5) < 0) __PYX_ERR(0, 272, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __pyx_v_ex = __pyx_t_6; + /*try:*/ { + + /* "httptools/parser/parser.pyx":273 + * 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 + */ + llhttp_set_error_reason(__pyx_v_parser, ((char const *)"`on_status` callback error")); + + /* "httptools/parser/parser.pyx":274 + * except BaseException as ex: + * cparser.llhttp_set_error_reason(parser, "`on_status` callback error") + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return cparser.HPE_USER + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":275 + * cparser.llhttp_set_error_reason(parser, "`on_status` callback error") + * pyparser._last_error = ex + * return cparser.HPE_USER # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = HPE_USER; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":272 + * 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 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_8 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_8; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":270 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_status(at[:length]) + * except BaseException as ex: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":267 + * + * + * cdef int cb_on_status(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_status", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":280 + * + * + * cdef int cb_on_header_field(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_header_field(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_header_field", 0); + + /* "httptools/parser/parser.pyx":282 + * 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]) + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":283 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._on_header_field(at[:length]) + * except BaseException as ex: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":284 + * 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") + */ + __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_at + 0, __pyx_v_length - 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 284, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_field(__pyx_v_pyparser, ((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 284, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "httptools/parser/parser.pyx":283 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._on_header_field(at[:length]) + * except BaseException as ex: + */ + } + + /* "httptools/parser/parser.pyx":290 + * return cparser.HPE_USER + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "httptools/parser/parser.pyx":285 + * 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 + */ + __pyx_t_6 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_6) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_header_field", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_1, &__pyx_t_7) < 0) __PYX_ERR(0, 285, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_ex = __pyx_t_1; + /*try:*/ { + + /* "httptools/parser/parser.pyx":286 + * 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 + */ + llhttp_set_error_reason(__pyx_v_parser, ((char const *)"`on_header_field` callback error")); + + /* "httptools/parser/parser.pyx":287 + * except BaseException as ex: + * cparser.llhttp_set_error_reason(parser, "`on_header_field` callback error") + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return cparser.HPE_USER + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":288 + * cparser.llhttp_set_error_reason(parser, "`on_header_field` callback error") + * pyparser._last_error = ex + * return cparser.HPE_USER # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = HPE_USER; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":285 + * 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 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_6 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_6; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":283 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._on_header_field(at[:length]) + * except BaseException as ex: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":280 + * + * + * cdef int cb_on_header_field(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_header_field", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":293 + * + * + * cdef int cb_on_header_value(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_header_value(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_header_value", 0); + + /* "httptools/parser/parser.pyx":295 + * 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]) + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":296 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._on_header_value(at[:length]) + * except BaseException as ex: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":297 + * 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") + */ + __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_at + 0, __pyx_v_length - 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 297, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_header_value(__pyx_v_pyparser, ((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 297, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "httptools/parser/parser.pyx":296 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._on_header_value(at[:length]) + * except BaseException as ex: + */ + } + + /* "httptools/parser/parser.pyx":303 + * return cparser.HPE_USER + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + + /* "httptools/parser/parser.pyx":298 + * 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 + */ + __pyx_t_6 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_6) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_header_value", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_1, &__pyx_t_7) < 0) __PYX_ERR(0, 298, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_ex = __pyx_t_1; + /*try:*/ { + + /* "httptools/parser/parser.pyx":299 + * 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 + */ + llhttp_set_error_reason(__pyx_v_parser, ((char const *)"`on_header_value` callback error")); + + /* "httptools/parser/parser.pyx":300 + * except BaseException as ex: + * cparser.llhttp_set_error_reason(parser, "`on_header_value` callback error") + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return cparser.HPE_USER + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":301 + * cparser.llhttp_set_error_reason(parser, "`on_header_value` callback error") + * pyparser._last_error = ex + * return cparser.HPE_USER # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = HPE_USER; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":298 + * 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 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_6 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_6; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":296 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._on_header_value(at[:length]) + * except BaseException as ex: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":293 + * + * + * cdef int cb_on_header_value(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_header_value", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":306 + * + * + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_headers_complete(llhttp_t *__pyx_v_parser) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + int __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_headers_complete", 0); + + /* "httptools/parser/parser.pyx":307 + * + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: + * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< + * try: + * pyparser._on_headers_complete() + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":308 + * 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: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":309 + * cdef HttpParser pyparser = parser.data + * try: + * pyparser._on_headers_complete() # <<<<<<<<<<<<<< + * except BaseException as ex: + * pyparser._last_error = ex + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_headers_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 309, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":308 + * 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: + */ + } + + /* "httptools/parser/parser.pyx":314 + * return -1 + * else: + * if pyparser._cparser.upgrade: # <<<<<<<<<<<<<< + * return 1 + * else: + */ + /*else:*/ { + __pyx_t_5 = (__pyx_v_pyparser->_cparser->upgrade != 0); + if (__pyx_t_5) { + + /* "httptools/parser/parser.pyx":315 + * else: + * if pyparser._cparser.upgrade: + * return 1 # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = 1; + goto __pyx_L6_except_return; + + /* "httptools/parser/parser.pyx":314 + * return -1 + * else: + * if pyparser._cparser.upgrade: # <<<<<<<<<<<<<< + * return 1 + * else: + */ + } + + /* "httptools/parser/parser.pyx":317 + * return 1 + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":310 + * try: + * pyparser._on_headers_complete() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + __pyx_t_6 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_6) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_headers_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_7, &__pyx_t_8) < 0) __PYX_ERR(0, 310, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __pyx_v_ex = __pyx_t_7; + /*try:*/ { + + /* "httptools/parser/parser.pyx":311 + * pyparser._on_headers_complete() + * except BaseException as ex: + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return -1 + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":312 + * except BaseException as ex: + * pyparser._last_error = ex + * return -1 # <<<<<<<<<<<<<< + * else: + * if pyparser._cparser.upgrade: + */ + __pyx_r = -1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L14_return; + } + + /* "httptools/parser/parser.pyx":310 + * try: + * pyparser._on_headers_complete() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + /*finally:*/ { + __pyx_L14_return: { + __pyx_t_6 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_6; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":308 + * 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: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":306 + * + * + * cdef int cb_on_headers_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_headers_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":320 + * + * + * cdef int cb_on_body(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_body(llhttp_t *__pyx_v_parser, char const *__pyx_v_at, size_t __pyx_v_length) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_t_8; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_body", 0); + + /* "httptools/parser/parser.pyx":322 + * 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]) + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":323 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_body(at[:length]) + * except BaseException as ex: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":324 + * 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") + */ + __pyx_t_5 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_at + 0, __pyx_v_length - 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 324, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_v_pyparser->_proto_on_body); + __pyx_t_6 = __pyx_v_pyparser->_proto_on_body; __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_6, function); + } + } + __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 324, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":323 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_body(at[:length]) + * except BaseException as ex: + */ + } + + /* "httptools/parser/parser.pyx":330 + * return cparser.HPE_USER + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "httptools/parser/parser.pyx":325 + * 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 + */ + __pyx_t_8 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_8) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_body", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_5) < 0) __PYX_ERR(0, 325, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __pyx_v_ex = __pyx_t_6; + /*try:*/ { + + /* "httptools/parser/parser.pyx":326 + * 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 + */ + llhttp_set_error_reason(__pyx_v_parser, ((char const *)"`on_body` callback error")); + + /* "httptools/parser/parser.pyx":327 + * except BaseException as ex: + * cparser.llhttp_set_error_reason(parser, "`on_body` callback error") + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return cparser.HPE_USER + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":328 + * cparser.llhttp_set_error_reason(parser, "`on_body` callback error") + * pyparser._last_error = ex + * return cparser.HPE_USER # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = HPE_USER; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":325 + * 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 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_8 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_8; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":323 + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + * try: # <<<<<<<<<<<<<< + * pyparser._proto_on_body(at[:length]) + * except BaseException as ex: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":320 + * + * + * cdef int cb_on_body(cparser.llhttp_t* parser, # <<<<<<<<<<<<<< + * const char *at, size_t length) except -1: + * cdef HttpParser pyparser = parser.data + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_body", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":333 + * + * + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_message_complete(llhttp_t *__pyx_v_parser) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_message_complete", 0); + + /* "httptools/parser/parser.pyx":334 + * + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: + * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< + * try: + * pyparser._proto_on_message_complete() + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":335 + * 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: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":336 + * cdef HttpParser pyparser = parser.data + * try: + * pyparser._proto_on_message_complete() # <<<<<<<<<<<<<< + * except BaseException as ex: + * pyparser._last_error = ex + */ + __Pyx_INCREF(__pyx_v_pyparser->_proto_on_message_complete); + __pyx_t_5 = __pyx_v_pyparser->_proto_on_message_complete; __pyx_t_6 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_6)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallNoArg(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 336, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":335 + * 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: + */ + } + + /* "httptools/parser/parser.pyx":341 + * return -1 + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + + /* "httptools/parser/parser.pyx":337 + * try: + * pyparser._proto_on_message_complete() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + __pyx_t_7 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_7) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_message_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_5, &__pyx_t_6) < 0) __PYX_ERR(0, 337, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_INCREF(__pyx_t_5); + __pyx_v_ex = __pyx_t_5; + /*try:*/ { + + /* "httptools/parser/parser.pyx":338 + * pyparser._proto_on_message_complete() + * except BaseException as ex: + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return -1 + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":339 + * except BaseException as ex: + * pyparser._last_error = ex + * return -1 # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = -1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":337 + * try: + * pyparser._proto_on_message_complete() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_7 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_7; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":335 + * 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: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":333 + * + * + * cdef int cb_on_message_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_message_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":344 + * + * + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_chunk_header(llhttp_t *__pyx_v_parser) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_chunk_header", 0); + + /* "httptools/parser/parser.pyx":345 + * + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: + * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< + * try: + * pyparser._on_chunk_header() + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":346 + * 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: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":347 + * cdef HttpParser pyparser = parser.data + * try: + * pyparser._on_chunk_header() # <<<<<<<<<<<<<< + * except BaseException as ex: + * pyparser._last_error = ex + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_chunk_header(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 347, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":346 + * 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: + */ + } + + /* "httptools/parser/parser.pyx":352 + * return -1 + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":348 + * try: + * pyparser._on_chunk_header() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + __pyx_t_5 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_5) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_chunk_header", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 348, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_6); + __pyx_v_ex = __pyx_t_6; + /*try:*/ { + + /* "httptools/parser/parser.pyx":349 + * pyparser._on_chunk_header() + * except BaseException as ex: + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return -1 + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":350 + * except BaseException as ex: + * pyparser._last_error = ex + * return -1 # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = -1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":348 + * try: + * pyparser._on_chunk_header() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_5 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_5; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":346 + * 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: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":344 + * + * + * cdef int cb_on_chunk_header(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_chunk_header", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":355 + * + * + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + +static int __pyx_f_9httptools_6parser_6parser_cb_on_chunk_complete(llhttp_t *__pyx_v_parser) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *__pyx_v_pyparser = 0; + PyObject *__pyx_v_ex = NULL; + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cb_on_chunk_complete", 0); + + /* "httptools/parser/parser.pyx":356 + * + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: + * cdef HttpParser pyparser = parser.data # <<<<<<<<<<<<<< + * try: + * pyparser._on_chunk_complete() + */ + __pyx_t_1 = ((PyObject *)__pyx_v_parser->data); + __Pyx_INCREF(__pyx_t_1); + __pyx_v_pyparser = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":357 + * 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: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_4); + /*try:*/ { + + /* "httptools/parser/parser.pyx":358 + * cdef HttpParser pyparser = parser.data + * try: + * pyparser._on_chunk_complete() # <<<<<<<<<<<<<< + * except BaseException as ex: + * pyparser._last_error = ex + */ + __pyx_t_1 = ((struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser *)__pyx_v_pyparser->__pyx_vtab)->_on_chunk_complete(__pyx_v_pyparser); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 358, __pyx_L3_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":357 + * 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: + */ + } + + /* "httptools/parser/parser.pyx":363 + * return -1 + * else: + * return 0 # <<<<<<<<<<<<<< + * + * + */ + /*else:*/ { + __pyx_r = 0; + goto __pyx_L6_except_return; + } + __pyx_L3_error:; + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":359 + * try: + * pyparser._on_chunk_complete() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + __pyx_t_5 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_BaseException); + if (__pyx_t_5) { + __Pyx_AddTraceback("httptools.parser.parser.cb_on_chunk_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 359, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_6); + __pyx_v_ex = __pyx_t_6; + /*try:*/ { + + /* "httptools/parser/parser.pyx":360 + * pyparser._on_chunk_complete() + * except BaseException as ex: + * pyparser._last_error = ex # <<<<<<<<<<<<<< + * return -1 + * else: + */ + __Pyx_INCREF(__pyx_v_ex); + __Pyx_GIVEREF(__pyx_v_ex); + __Pyx_GOTREF(__pyx_v_pyparser->_last_error); + __Pyx_DECREF(__pyx_v_pyparser->_last_error); + __pyx_v_pyparser->_last_error = __pyx_v_ex; + + /* "httptools/parser/parser.pyx":361 + * except BaseException as ex: + * pyparser._last_error = ex + * return -1 # <<<<<<<<<<<<<< + * else: + * return 0 + */ + __pyx_r = -1; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L13_return; + } + + /* "httptools/parser/parser.pyx":359 + * try: + * pyparser._on_chunk_complete() + * except BaseException as ex: # <<<<<<<<<<<<<< + * pyparser._last_error = ex + * return -1 + */ + /*finally:*/ { + __pyx_L13_return: { + __pyx_t_5 = __pyx_r; + __Pyx_DECREF(__pyx_v_ex); + __pyx_v_ex = NULL; + __pyx_r = __pyx_t_5; + goto __pyx_L6_except_return; + } + } + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "httptools/parser/parser.pyx":357 + * 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: + */ + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L1_error; + __pyx_L6_except_return:; + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_XGIVEREF(__pyx_t_4); + __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); + goto __pyx_L0; + } + + /* "httptools/parser/parser.pyx":355 + * + * + * cdef int cb_on_chunk_complete(cparser.llhttp_t* parser) except -1: # <<<<<<<<<<<<<< + * cdef HttpParser pyparser = parser.data + * try: + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_AddTraceback("httptools.parser.parser.cb_on_chunk_complete", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_pyparser); + __Pyx_XDECREF(__pyx_v_ex); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/parser.pyx":366 + * + * + * cdef parser_error_from_errno(cparser.llhttp_t* parser, cparser.llhttp_errno_t errno): # <<<<<<<<<<<<<< + * cdef bytes reason = cparser.llhttp_get_error_reason(parser) + * + */ + +static PyObject *__pyx_f_9httptools_6parser_6parser_parser_error_from_errno(llhttp_t *__pyx_v_parser, llhttp_errno_t __pyx_v_errno) { + PyObject *__pyx_v_reason = 0; + PyObject *__pyx_v_cls = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("parser_error_from_errno", 0); + + /* "httptools/parser/parser.pyx":367 + * + * 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, + */ + __pyx_t_1 = __Pyx_PyBytes_FromString(llhttp_get_error_reason(__pyx_v_parser)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 367, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_reason = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":369 + * 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, + */ + switch (__pyx_v_errno) { + case HPE_CB_MESSAGE_BEGIN: + case HPE_CB_HEADERS_COMPLETE: + + /* "httptools/parser/parser.pyx":370 + * + * if errno in (cparser.HPE_CB_MESSAGE_BEGIN, + * cparser.HPE_CB_HEADERS_COMPLETE, # <<<<<<<<<<<<<< + * cparser.HPE_CB_MESSAGE_COMPLETE, + * cparser.HPE_CB_CHUNK_HEADER, + */ + case HPE_CB_MESSAGE_COMPLETE: + + /* "httptools/parser/parser.pyx":371 + * 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, + */ + case HPE_CB_CHUNK_HEADER: + + /* "httptools/parser/parser.pyx":372 + * cparser.HPE_CB_HEADERS_COMPLETE, + * cparser.HPE_CB_MESSAGE_COMPLETE, + * cparser.HPE_CB_CHUNK_HEADER, # <<<<<<<<<<<<<< + * cparser.HPE_CB_CHUNK_COMPLETE, + * cparser.HPE_USER): + */ + case HPE_CB_CHUNK_COMPLETE: + + /* "httptools/parser/parser.pyx":373 + * cparser.HPE_CB_MESSAGE_COMPLETE, + * cparser.HPE_CB_CHUNK_HEADER, + * cparser.HPE_CB_CHUNK_COMPLETE, # <<<<<<<<<<<<<< + * cparser.HPE_USER): + * cls = HttpParserCallbackError + */ + case HPE_USER: + + /* "httptools/parser/parser.pyx":375 + * cparser.HPE_CB_CHUNK_COMPLETE, + * cparser.HPE_USER): + * cls = HttpParserCallbackError # <<<<<<<<<<<<<< + * + * elif errno == cparser.HPE_INVALID_STATUS: + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpParserCallbackError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 375, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_cls = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":369 + * 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, + */ + break; + case HPE_INVALID_STATUS: + + /* "httptools/parser/parser.pyx":378 + * + * elif errno == cparser.HPE_INVALID_STATUS: + * cls = HttpParserInvalidStatusError # <<<<<<<<<<<<<< + * + * elif errno == cparser.HPE_INVALID_METHOD: + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpParserInvalidStatusError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 378, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_cls = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":377 + * cls = HttpParserCallbackError + * + * elif errno == cparser.HPE_INVALID_STATUS: # <<<<<<<<<<<<<< + * cls = HttpParserInvalidStatusError + * + */ + break; + case HPE_INVALID_METHOD: + + /* "httptools/parser/parser.pyx":381 + * + * elif errno == cparser.HPE_INVALID_METHOD: + * cls = HttpParserInvalidMethodError # <<<<<<<<<<<<<< + * + * elif errno == cparser.HPE_INVALID_URL: + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpParserInvalidMethodError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 381, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_cls = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":380 + * cls = HttpParserInvalidStatusError + * + * elif errno == cparser.HPE_INVALID_METHOD: # <<<<<<<<<<<<<< + * cls = HttpParserInvalidMethodError + * + */ + break; + case HPE_INVALID_URL: + + /* "httptools/parser/parser.pyx":384 + * + * elif errno == cparser.HPE_INVALID_URL: + * cls = HttpParserInvalidURLError # <<<<<<<<<<<<<< + * + * else: + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpParserInvalidURLError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 384, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_cls = __pyx_t_1; + __pyx_t_1 = 0; + + /* "httptools/parser/parser.pyx":383 + * cls = HttpParserInvalidMethodError + * + * elif errno == cparser.HPE_INVALID_URL: # <<<<<<<<<<<<<< + * cls = HttpParserInvalidURLError + * + */ + break; + default: + + /* "httptools/parser/parser.pyx":387 + * + * else: + * cls = HttpParserError # <<<<<<<<<<<<<< + * + * return cls(reason.decode('latin-1')) + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_HttpParserError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 387, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_cls = __pyx_t_1; + __pyx_t_1 = 0; + break; + } + + /* "httptools/parser/parser.pyx":389 + * cls = HttpParserError + * + * return cls(reason.decode('latin-1')) # <<<<<<<<<<<<<< + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_2 = __Pyx_decode_bytes(__pyx_v_reason, 0, PY_SSIZE_T_MAX, NULL, NULL, PyUnicode_DecodeLatin1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 389, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_INCREF(__pyx_v_cls); + __pyx_t_3 = __pyx_v_cls; __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 389, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "httptools/parser/parser.pyx":366 + * + * + * cdef parser_error_from_errno(cparser.llhttp_t* parser, cparser.llhttp_errno_t errno): # <<<<<<<<<<<<<< + * cdef bytes reason = cparser.llhttp_get_error_reason(parser) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("httptools.parser.parser.parser_error_from_errno", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_reason); + __Pyx_XDECREF(__pyx_v_cls); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} +static struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser __pyx_vtable_9httptools_6parser_6parser_HttpParser; + +static PyObject *__pyx_tp_new_9httptools_6parser_6parser_HttpParser(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *p; + PyObject *o; + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)o); + p->__pyx_vtab = __pyx_vtabptr_9httptools_6parser_6parser_HttpParser; + p->_current_header_name = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->_current_header_value = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->_proto_on_url = Py_None; Py_INCREF(Py_None); + p->_proto_on_status = Py_None; Py_INCREF(Py_None); + p->_proto_on_body = Py_None; Py_INCREF(Py_None); + p->_proto_on_header = Py_None; Py_INCREF(Py_None); + p->_proto_on_headers_complete = Py_None; Py_INCREF(Py_None); + p->_proto_on_message_complete = Py_None; Py_INCREF(Py_None); + p->_proto_on_chunk_header = Py_None; Py_INCREF(Py_None); + p->_proto_on_chunk_complete = Py_None; Py_INCREF(Py_None); + p->_proto_on_message_begin = Py_None; Py_INCREF(Py_None); + p->_last_error = Py_None; Py_INCREF(Py_None); + p->py_buf.obj = NULL; + if (unlikely(__pyx_pw_9httptools_6parser_6parser_10HttpParser_1__cinit__(o, __pyx_empty_tuple, NULL) < 0)) goto bad; + return o; + bad: + Py_DECREF(o); o = 0; + return NULL; +} + +static void __pyx_tp_dealloc_9httptools_6parser_6parser_HttpParser(PyObject *o) { + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *p = (struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + { + PyObject *etype, *eval, *etb; + PyErr_Fetch(&etype, &eval, &etb); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1); + __pyx_pw_9httptools_6parser_6parser_10HttpParser_3__dealloc__(o); + __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1); + PyErr_Restore(etype, eval, etb); + } + Py_CLEAR(p->_current_header_name); + Py_CLEAR(p->_current_header_value); + Py_CLEAR(p->_proto_on_url); + Py_CLEAR(p->_proto_on_status); + Py_CLEAR(p->_proto_on_body); + Py_CLEAR(p->_proto_on_header); + Py_CLEAR(p->_proto_on_headers_complete); + Py_CLEAR(p->_proto_on_message_complete); + Py_CLEAR(p->_proto_on_chunk_header); + Py_CLEAR(p->_proto_on_chunk_complete); + Py_CLEAR(p->_proto_on_message_begin); + Py_CLEAR(p->_last_error); + (*Py_TYPE(o)->tp_free)(o); +} + +static int __pyx_tp_traverse_9httptools_6parser_6parser_HttpParser(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *p = (struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)o; + if (p->_proto_on_url) { + e = (*v)(p->_proto_on_url, a); if (e) return e; + } + if (p->_proto_on_status) { + e = (*v)(p->_proto_on_status, a); if (e) return e; + } + if (p->_proto_on_body) { + e = (*v)(p->_proto_on_body, a); if (e) return e; + } + if (p->_proto_on_header) { + e = (*v)(p->_proto_on_header, a); if (e) return e; + } + if (p->_proto_on_headers_complete) { + e = (*v)(p->_proto_on_headers_complete, a); if (e) return e; + } + if (p->_proto_on_message_complete) { + e = (*v)(p->_proto_on_message_complete, a); if (e) return e; + } + if (p->_proto_on_chunk_header) { + e = (*v)(p->_proto_on_chunk_header, a); if (e) return e; + } + if (p->_proto_on_chunk_complete) { + e = (*v)(p->_proto_on_chunk_complete, a); if (e) return e; + } + if (p->_proto_on_message_begin) { + e = (*v)(p->_proto_on_message_begin, a); if (e) return e; + } + if (p->_last_error) { + e = (*v)(p->_last_error, a); if (e) return e; + } + if (p->py_buf.obj) { + e = (*v)(p->py_buf.obj, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_9httptools_6parser_6parser_HttpParser(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_9httptools_6parser_6parser_HttpParser *p = (struct __pyx_obj_9httptools_6parser_6parser_HttpParser *)o; + tmp = ((PyObject*)p->_proto_on_url); + p->_proto_on_url = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_status); + p->_proto_on_status = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_body); + p->_proto_on_body = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_header); + p->_proto_on_header = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_headers_complete); + p->_proto_on_headers_complete = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_message_complete); + p->_proto_on_message_complete = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_chunk_header); + p->_proto_on_chunk_header = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_chunk_complete); + p->_proto_on_chunk_complete = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_proto_on_message_begin); + p->_proto_on_message_begin = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + tmp = ((PyObject*)p->_last_error); + p->_last_error = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + Py_CLEAR(p->py_buf.obj); + return 0; +} + +static PyMethodDef __pyx_methods_9httptools_6parser_6parser_HttpParser[] = { + {"get_http_version", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_10HttpParser_5get_http_version, METH_NOARGS, 0}, + {"should_keep_alive", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_10HttpParser_7should_keep_alive, METH_NOARGS, 0}, + {"should_upgrade", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_10HttpParser_9should_upgrade, METH_NOARGS, 0}, + {"feed_data", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_10HttpParser_11feed_data, METH_O, 0}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_10HttpParser_13__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_10HttpParser_15__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_9httptools_6parser_6parser_HttpParser = { + PyVarObject_HEAD_INIT(0, 0) + "httptools.parser.parser.HttpParser", /*tp_name*/ + sizeof(struct __pyx_obj_9httptools_6parser_6parser_HttpParser), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_9httptools_6parser_6parser_HttpParser, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_9httptools_6parser_6parser_HttpParser, /*tp_traverse*/ + __pyx_tp_clear_9httptools_6parser_6parser_HttpParser, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_9httptools_6parser_6parser_HttpParser, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_9httptools_6parser_6parser_HttpParser, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; +static struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpRequestParser __pyx_vtable_9httptools_6parser_6parser_HttpRequestParser; + +static PyObject *__pyx_tp_new_9httptools_6parser_6parser_HttpRequestParser(PyTypeObject *t, PyObject *a, PyObject *k) { + struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *p; + PyObject *o = __pyx_tp_new_9httptools_6parser_6parser_HttpParser(t, a, k); + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser *)o); + p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser*)__pyx_vtabptr_9httptools_6parser_6parser_HttpRequestParser; + return o; +} + +static PyMethodDef __pyx_methods_9httptools_6parser_6parser_HttpRequestParser[] = { + {"get_method", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_3get_method, METH_NOARGS, 0}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_5__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_7__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_9httptools_6parser_6parser_HttpRequestParser = { + PyVarObject_HEAD_INIT(0, 0) + "httptools.parser.parser.HttpRequestParser", /*tp_name*/ + sizeof(struct __pyx_obj_9httptools_6parser_6parser_HttpRequestParser), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_9httptools_6parser_6parser_HttpParser, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_9httptools_6parser_6parser_HttpParser, /*tp_traverse*/ + __pyx_tp_clear_9httptools_6parser_6parser_HttpParser, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_9httptools_6parser_6parser_HttpRequestParser, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_9httptools_6parser_6parser_17HttpRequestParser_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_9httptools_6parser_6parser_HttpRequestParser, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; +static struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpResponseParser __pyx_vtable_9httptools_6parser_6parser_HttpResponseParser; + +static PyObject *__pyx_tp_new_9httptools_6parser_6parser_HttpResponseParser(PyTypeObject *t, PyObject *a, PyObject *k) { + struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *p; + PyObject *o = __pyx_tp_new_9httptools_6parser_6parser_HttpParser(t, a, k); + if (unlikely(!o)) return 0; + p = ((struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser *)o); + p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_9httptools_6parser_6parser_HttpParser*)__pyx_vtabptr_9httptools_6parser_6parser_HttpResponseParser; + return o; +} + +static PyMethodDef __pyx_methods_9httptools_6parser_6parser_HttpResponseParser[] = { + {"get_status_code", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_3get_status_code, METH_NOARGS, 0}, + {"__reduce_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_5__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_7__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_9httptools_6parser_6parser_HttpResponseParser = { + PyVarObject_HEAD_INIT(0, 0) + "httptools.parser.parser.HttpResponseParser", /*tp_name*/ + sizeof(struct __pyx_obj_9httptools_6parser_6parser_HttpResponseParser), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_9httptools_6parser_6parser_HttpParser, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_9httptools_6parser_6parser_HttpParser, /*tp_traverse*/ + __pyx_tp_clear_9httptools_6parser_6parser_HttpParser, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_9httptools_6parser_6parser_HttpResponseParser, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + __pyx_pw_9httptools_6parser_6parser_18HttpResponseParser_1__init__, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_9httptools_6parser_6parser_HttpResponseParser, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_parser(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_parser}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "parser", + 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_u_, __pyx_k_, sizeof(__pyx_k_), 0, 1, 0, 0}, + {&__pyx_n_s_BaseException, __pyx_k_BaseException, sizeof(__pyx_k_BaseException), 0, 0, 1, 1}, + {&__pyx_n_s_HttpParserCallbackError, __pyx_k_HttpParserCallbackError, sizeof(__pyx_k_HttpParserCallbackError), 0, 0, 1, 1}, + {&__pyx_n_s_HttpParserError, __pyx_k_HttpParserError, sizeof(__pyx_k_HttpParserError), 0, 0, 1, 1}, + {&__pyx_n_s_HttpParserInvalidMethodError, __pyx_k_HttpParserInvalidMethodError, sizeof(__pyx_k_HttpParserInvalidMethodError), 0, 0, 1, 1}, + {&__pyx_n_s_HttpParserInvalidStatusError, __pyx_k_HttpParserInvalidStatusError, sizeof(__pyx_k_HttpParserInvalidStatusError), 0, 0, 1, 1}, + {&__pyx_n_s_HttpParserInvalidURLError, __pyx_k_HttpParserInvalidURLError, sizeof(__pyx_k_HttpParserInvalidURLError), 0, 0, 1, 1}, + {&__pyx_n_s_HttpParserUpgrade, __pyx_k_HttpParserUpgrade, sizeof(__pyx_k_HttpParserUpgrade), 0, 0, 1, 1}, + {&__pyx_n_s_HttpRequestParser, __pyx_k_HttpRequestParser, sizeof(__pyx_k_HttpRequestParser), 0, 0, 1, 1}, + {&__pyx_n_u_HttpRequestParser, __pyx_k_HttpRequestParser, sizeof(__pyx_k_HttpRequestParser), 0, 1, 0, 1}, + {&__pyx_n_s_HttpResponseParser, __pyx_k_HttpResponseParser, sizeof(__pyx_k_HttpResponseParser), 0, 0, 1, 1}, + {&__pyx_n_u_HttpResponseParser, __pyx_k_HttpResponseParser, sizeof(__pyx_k_HttpResponseParser), 0, 1, 0, 1}, + {&__pyx_n_s_MemoryError, __pyx_k_MemoryError, sizeof(__pyx_k_MemoryError), 0, 0, 1, 1}, + {&__pyx_n_s_TypeError, __pyx_k_TypeError, sizeof(__pyx_k_TypeError), 0, 0, 1, 1}, + {&__pyx_n_s_all, __pyx_k_all, sizeof(__pyx_k_all), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_context, __pyx_k_context, sizeof(__pyx_k_context), 0, 0, 1, 1}, + {&__pyx_n_s_errors, __pyx_k_errors, sizeof(__pyx_k_errors), 0, 0, 1, 1}, + {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1}, + {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1}, + {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, + {&__pyx_kp_u_invalid_headers_state, __pyx_k_invalid_headers_state, sizeof(__pyx_k_invalid_headers_state), 0, 1, 0, 0}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_kp_s_no_default___reduce___due_to_non, __pyx_k_no_default___reduce___due_to_non, sizeof(__pyx_k_no_default___reduce___due_to_non), 0, 0, 1, 0}, + {&__pyx_n_u_on_body, __pyx_k_on_body, sizeof(__pyx_k_on_body), 0, 1, 0, 1}, + {&__pyx_n_u_on_chunk_complete, __pyx_k_on_chunk_complete, sizeof(__pyx_k_on_chunk_complete), 0, 1, 0, 1}, + {&__pyx_n_u_on_chunk_header, __pyx_k_on_chunk_header, sizeof(__pyx_k_on_chunk_header), 0, 1, 0, 1}, + {&__pyx_n_u_on_header, __pyx_k_on_header, sizeof(__pyx_k_on_header), 0, 1, 0, 1}, + {&__pyx_n_u_on_headers_complete, __pyx_k_on_headers_complete, sizeof(__pyx_k_on_headers_complete), 0, 1, 0, 1}, + {&__pyx_n_u_on_message_begin, __pyx_k_on_message_begin, sizeof(__pyx_k_on_message_begin), 0, 1, 0, 1}, + {&__pyx_n_u_on_message_complete, __pyx_k_on_message_complete, sizeof(__pyx_k_on_message_complete), 0, 1, 0, 1}, + {&__pyx_n_u_on_status, __pyx_k_on_status, sizeof(__pyx_k_on_status), 0, 1, 0, 1}, + {&__pyx_n_u_on_url, __pyx_k_on_url, sizeof(__pyx_k_on_url), 0, 1, 0, 1}, + {&__pyx_n_s_protocol, __pyx_k_protocol, sizeof(__pyx_k_protocol), 0, 0, 1, 1}, + {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1}, + {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, + {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, + {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_MemoryError = __Pyx_GetBuiltinName(__pyx_n_s_MemoryError); if (!__pyx_builtin_MemoryError) __PYX_ERR(0, 48, __pyx_L1_error) + __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(1, 2, __pyx_L1_error) + __pyx_builtin_BaseException = __Pyx_GetBuiltinName(__pyx_n_s_BaseException); if (!__pyx_builtin_BaseException) __PYX_ERR(0, 247, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__2); + __Pyx_GIVEREF(__pyx_tuple__2); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__3); + __Pyx_GIVEREF(__pyx_tuple__3); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__4); + __Pyx_GIVEREF(__pyx_tuple__4); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__5); + __Pyx_GIVEREF(__pyx_tuple__5); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__6); + __Pyx_GIVEREF(__pyx_tuple__6); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__7); + __Pyx_GIVEREF(__pyx_tuple__7); + + /* "httptools/parser/parser.pyx":22 + * + * + * __all__ = ('HttpRequestParser', 'HttpResponseParser') # <<<<<<<<<<<<<< + * + * + */ + __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_u_HttpRequestParser, __pyx_n_u_HttpResponseParser); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__8); + __Pyx_GIVEREF(__pyx_tuple__8); + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __pyx_vtabptr_9httptools_6parser_6parser_HttpParser = &__pyx_vtable_9httptools_6parser_6parser_HttpParser; + __pyx_vtable_9httptools_6parser_6parser_HttpParser._init = (PyObject *(*)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *, PyObject *, llhttp_type_t))__pyx_f_9httptools_6parser_6parser_10HttpParser__init; + __pyx_vtable_9httptools_6parser_6parser_HttpParser._maybe_call_on_header = (PyObject *(*)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *))__pyx_f_9httptools_6parser_6parser_10HttpParser__maybe_call_on_header; + __pyx_vtable_9httptools_6parser_6parser_HttpParser._on_header_field = (PyObject *(*)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *, PyObject *))__pyx_f_9httptools_6parser_6parser_10HttpParser__on_header_field; + __pyx_vtable_9httptools_6parser_6parser_HttpParser._on_header_value = (PyObject *(*)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *, PyObject *))__pyx_f_9httptools_6parser_6parser_10HttpParser__on_header_value; + __pyx_vtable_9httptools_6parser_6parser_HttpParser._on_headers_complete = (PyObject *(*)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *))__pyx_f_9httptools_6parser_6parser_10HttpParser__on_headers_complete; + __pyx_vtable_9httptools_6parser_6parser_HttpParser._on_chunk_header = (PyObject *(*)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *))__pyx_f_9httptools_6parser_6parser_10HttpParser__on_chunk_header; + __pyx_vtable_9httptools_6parser_6parser_HttpParser._on_chunk_complete = (PyObject *(*)(struct __pyx_obj_9httptools_6parser_6parser_HttpParser *))__pyx_f_9httptools_6parser_6parser_10HttpParser__on_chunk_complete; + if (PyType_Ready(&__pyx_type_9httptools_6parser_6parser_HttpParser) < 0) __PYX_ERR(0, 26, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_9httptools_6parser_6parser_HttpParser.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9httptools_6parser_6parser_HttpParser.tp_dictoffset && __pyx_type_9httptools_6parser_6parser_HttpParser.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_9httptools_6parser_6parser_HttpParser.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (__Pyx_SetVtable(__pyx_type_9httptools_6parser_6parser_HttpParser.tp_dict, __pyx_vtabptr_9httptools_6parser_6parser_HttpParser) < 0) __PYX_ERR(0, 26, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9httptools_6parser_6parser_HttpParser) < 0) __PYX_ERR(0, 26, __pyx_L1_error) + __pyx_ptype_9httptools_6parser_6parser_HttpParser = &__pyx_type_9httptools_6parser_6parser_HttpParser; + __pyx_vtabptr_9httptools_6parser_6parser_HttpRequestParser = &__pyx_vtable_9httptools_6parser_6parser_HttpRequestParser; + __pyx_vtable_9httptools_6parser_6parser_HttpRequestParser.__pyx_base = *__pyx_vtabptr_9httptools_6parser_6parser_HttpParser; + __pyx_type_9httptools_6parser_6parser_HttpRequestParser.tp_base = __pyx_ptype_9httptools_6parser_6parser_HttpParser; + if (PyType_Ready(&__pyx_type_9httptools_6parser_6parser_HttpRequestParser) < 0) __PYX_ERR(0, 215, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_9httptools_6parser_6parser_HttpRequestParser.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9httptools_6parser_6parser_HttpRequestParser.tp_dictoffset && __pyx_type_9httptools_6parser_6parser_HttpRequestParser.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_9httptools_6parser_6parser_HttpRequestParser.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (__Pyx_SetVtable(__pyx_type_9httptools_6parser_6parser_HttpRequestParser.tp_dict, __pyx_vtabptr_9httptools_6parser_6parser_HttpRequestParser) < 0) __PYX_ERR(0, 215, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_HttpRequestParser, (PyObject *)&__pyx_type_9httptools_6parser_6parser_HttpRequestParser) < 0) __PYX_ERR(0, 215, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9httptools_6parser_6parser_HttpRequestParser) < 0) __PYX_ERR(0, 215, __pyx_L1_error) + __pyx_ptype_9httptools_6parser_6parser_HttpRequestParser = &__pyx_type_9httptools_6parser_6parser_HttpRequestParser; + __pyx_vtabptr_9httptools_6parser_6parser_HttpResponseParser = &__pyx_vtable_9httptools_6parser_6parser_HttpResponseParser; + __pyx_vtable_9httptools_6parser_6parser_HttpResponseParser.__pyx_base = *__pyx_vtabptr_9httptools_6parser_6parser_HttpParser; + __pyx_type_9httptools_6parser_6parser_HttpResponseParser.tp_base = __pyx_ptype_9httptools_6parser_6parser_HttpParser; + if (PyType_Ready(&__pyx_type_9httptools_6parser_6parser_HttpResponseParser) < 0) __PYX_ERR(0, 229, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_9httptools_6parser_6parser_HttpResponseParser.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9httptools_6parser_6parser_HttpResponseParser.tp_dictoffset && __pyx_type_9httptools_6parser_6parser_HttpResponseParser.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_9httptools_6parser_6parser_HttpResponseParser.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (__Pyx_SetVtable(__pyx_type_9httptools_6parser_6parser_HttpResponseParser.tp_dict, __pyx_vtabptr_9httptools_6parser_6parser_HttpResponseParser) < 0) __PYX_ERR(0, 229, __pyx_L1_error) + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_HttpResponseParser, (PyObject *)&__pyx_type_9httptools_6parser_6parser_HttpResponseParser) < 0) __PYX_ERR(0, 229, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9httptools_6parser_6parser_HttpResponseParser) < 0) __PYX_ERR(0, 229, __pyx_L1_error) + __pyx_ptype_9httptools_6parser_6parser_HttpResponseParser = &__pyx_type_9httptools_6parser_6parser_HttpResponseParser; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(3, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(4, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(4, 15, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#ifndef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#elif PY_MAJOR_VERSION < 3 +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" void +#else +#define __Pyx_PyMODINIT_FUNC void +#endif +#else +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyObject * +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initparser(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initparser(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_parser(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_parser(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_parser(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'parser' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_parser(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + PyEval_InitThreads(); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("parser", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main_httptools__parser__parser) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "httptools.parser.parser")) { + if (unlikely(PyDict_SetItemString(modules, "httptools.parser.parser", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + if (unlikely(__Pyx_modinit_type_init_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + if (unlikely(__Pyx_modinit_type_import_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "httptools/parser/parser.pyx":11 + * + * + * from .errors import (HttpParserError, # <<<<<<<<<<<<<< + * HttpParserCallbackError, + * HttpParserInvalidStatusError, + */ + __pyx_t_1 = PyList_New(6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_HttpParserError); + __Pyx_GIVEREF(__pyx_n_s_HttpParserError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_HttpParserError); + __Pyx_INCREF(__pyx_n_s_HttpParserCallbackError); + __Pyx_GIVEREF(__pyx_n_s_HttpParserCallbackError); + PyList_SET_ITEM(__pyx_t_1, 1, __pyx_n_s_HttpParserCallbackError); + __Pyx_INCREF(__pyx_n_s_HttpParserInvalidStatusError); + __Pyx_GIVEREF(__pyx_n_s_HttpParserInvalidStatusError); + PyList_SET_ITEM(__pyx_t_1, 2, __pyx_n_s_HttpParserInvalidStatusError); + __Pyx_INCREF(__pyx_n_s_HttpParserInvalidMethodError); + __Pyx_GIVEREF(__pyx_n_s_HttpParserInvalidMethodError); + PyList_SET_ITEM(__pyx_t_1, 3, __pyx_n_s_HttpParserInvalidMethodError); + __Pyx_INCREF(__pyx_n_s_HttpParserInvalidURLError); + __Pyx_GIVEREF(__pyx_n_s_HttpParserInvalidURLError); + PyList_SET_ITEM(__pyx_t_1, 4, __pyx_n_s_HttpParserInvalidURLError); + __Pyx_INCREF(__pyx_n_s_HttpParserUpgrade); + __Pyx_GIVEREF(__pyx_n_s_HttpParserUpgrade); + PyList_SET_ITEM(__pyx_t_1, 5, __pyx_n_s_HttpParserUpgrade); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_errors, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpParserError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpParserError, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpParserCallbackError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpParserCallbackError, __pyx_t_1) < 0) __PYX_ERR(0, 12, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpParserInvalidStatusError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpParserInvalidStatusError, __pyx_t_1) < 0) __PYX_ERR(0, 13, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpParserInvalidMethodError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpParserInvalidMethodError, __pyx_t_1) < 0) __PYX_ERR(0, 14, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpParserInvalidURLError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpParserInvalidURLError, __pyx_t_1) < 0) __PYX_ERR(0, 15, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpParserUpgrade); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpParserUpgrade, __pyx_t_1) < 0) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "httptools/parser/parser.pyx":22 + * + * + * __all__ = ('HttpRequestParser', 'HttpResponseParser') # <<<<<<<<<<<<<< + * + * + */ + if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_tuple__8) < 0) __PYX_ERR(0, 22, __pyx_L1_error) + + /* "httptools/parser/parser.pyx":1 + * #cython: language_level=3 # <<<<<<<<<<<<<< + * + * from __future__ import print_function + */ + __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init httptools.parser.parser", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init httptools.parser.parser"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* KeywordStringCheck */ +static int __Pyx_CheckKeywordStrings( + PyObject *kwdict, + const char* function_name, + int kw_allowed) +{ + PyObject* key = 0; + Py_ssize_t pos = 0; +#if CYTHON_COMPILING_IN_PYPY + if (!kw_allowed && PyDict_Next(kwdict, &pos, &key, 0)) + goto invalid_keyword; + return 1; +#else + while (PyDict_Next(kwdict, &pos, &key, 0)) { + #if PY_MAJOR_VERSION < 3 + if (unlikely(!PyString_Check(key))) + #endif + if (unlikely(!PyUnicode_Check(key))) + goto invalid_keyword_type; + } + if ((!kw_allowed) && unlikely(key)) + goto invalid_keyword; + return 1; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + return 0; +#endif +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif + return 0; +} + +/* PyErrExceptionMatches */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; icurexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; + if (unlikely(PyTuple_Check(err))) + return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); +} +#endif + +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* GetAttr */ +static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { +#if CYTHON_USE_TYPE_SLOTS +#if PY_MAJOR_VERSION >= 3 + if (likely(PyUnicode_Check(n))) +#else + if (likely(PyString_Check(n))) +#endif + return __Pyx_PyObject_GetAttrStr(o, n); +#endif + return PyObject_GetAttr(o, n); +} + +/* GetAttr3 */ +static PyObject *__Pyx_GetAttr3Default(PyObject *d) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + return NULL; + __Pyx_PyErr_Clear(); + Py_INCREF(d); + return d; +} +static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { + PyObject *r = __Pyx_GetAttr(o, n); + return (likely(r)) ? r : __Pyx_GetAttr3Default(d); +} + +/* PyFunctionFastCall */ +#if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyCFunctionFastCall */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = Py_TYPE(func)->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallNoArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, NULL, 0); + } +#endif +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) +#else + if (likely(PyCFunction_Check(func))) +#endif + { + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + +/* PyObjectCallOneArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (__Pyx_PyFastCFunction_Check(func)) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ +#if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* PyObjectCall2Args */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { + PyObject *args, *result = NULL; + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyFunction_FastCall(function, args, 2); + } + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyCFunction_FastCall(function, args, 2); + } + #endif + args = PyTuple_New(2); + if (unlikely(!args)) goto done; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + Py_INCREF(function); + result = __Pyx_PyObject_Call(function, args, NULL); + Py_DECREF(args); + Py_DECREF(function); +done: + return result; +} + +/* RaiseException */ +#if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, + CYTHON_UNUSED PyObject *cause) { + __Pyx_PyThreadState_declare + Py_XINCREF(type); + if (!value || value == Py_None) + value = NULL; + else + Py_INCREF(value); + if (!tb || tb == Py_None) + tb = NULL; + else { + Py_INCREF(tb); + if (!PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + } + if (PyType_Check(type)) { +#if CYTHON_COMPILING_IN_PYPY + if (!value) { + Py_INCREF(Py_None); + value = Py_None; + } +#endif + PyErr_NormalizeException(&type, &value, &tb); + } else { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + value = type; + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + } + __Pyx_PyThreadState_assign + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} +#else +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if CYTHON_COMPILING_IN_PYPY + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#else + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} +#endif + +/* GetException */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) +#endif +{ + PyObject *local_type, *local_value, *local_tb; +#if CYTHON_FAST_THREAD_STATE + PyObject *tmp_type, *tmp_value, *tmp_tb; + local_type = tstate->curexc_type; + local_value = tstate->curexc_value; + local_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#else + PyErr_Fetch(&local_type, &local_value, &local_tb); +#endif + PyErr_NormalizeException(&local_type, &local_value, &local_tb); +#if CYTHON_FAST_THREAD_STATE + if (unlikely(tstate->curexc_type)) +#else + if (unlikely(PyErr_Occurred())) +#endif + goto bad; + #if PY_MAJOR_VERSION >= 3 + if (local_tb) { + if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) + goto bad; + } + #endif + Py_XINCREF(local_tb); + Py_XINCREF(local_type); + Py_XINCREF(local_value); + *type = local_type; + *value = local_value; + *tb = local_tb; +#if CYTHON_FAST_THREAD_STATE + #if CYTHON_USE_EXC_INFO_STACK + { + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = local_type; + exc_info->exc_value = local_value; + exc_info->exc_traceback = local_tb; + } + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = local_type; + tstate->exc_value = local_value; + tstate->exc_traceback = local_tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#else + PyErr_SetExcInfo(local_type, local_value, local_tb); +#endif + return 0; +bad: + *type = 0; + *value = 0; + *tb = 0; + Py_XDECREF(local_type); + Py_XDECREF(local_value); + Py_XDECREF(local_tb); + return -1; +} + +/* SwapException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = *type; + exc_info->exc_value = *value; + exc_info->exc_traceback = *tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = *type; + tstate->exc_value = *value; + tstate->exc_traceback = *tb; + #endif + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb); + PyErr_SetExcInfo(*type, *value, *tb); + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#endif + +/* GetTopmostException */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* SaveResetException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + *type = exc_info->exc_type; + *value = exc_info->exc_value; + *tb = exc_info->exc_traceback; + #else + *type = tstate->exc_type; + *value = tstate->exc_value; + *tb = tstate->exc_traceback; + #endif + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); +} +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_traceback = tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = type; + tstate->exc_value = value; + tstate->exc_traceback = tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +#endif + +/* PyObjectSetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_setattro)) + return tp->tp_setattro(obj, attr_name, value); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_setattr)) + return tp->tp_setattr(obj, PyString_AS_STRING(attr_name), value); +#endif + return PyObject_SetAttr(obj, attr_name, value); +} +#endif + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* decode_c_bytes */ +static CYTHON_INLINE PyObject* __Pyx_decode_c_bytes( + const char* cstring, Py_ssize_t length, Py_ssize_t start, Py_ssize_t stop, + const char* encoding, const char* errors, + PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { + if (unlikely((start < 0) | (stop < 0))) { + if (start < 0) { + start += length; + if (start < 0) + start = 0; + } + if (stop < 0) + stop += length; + } + if (stop > length) + stop = length; + if (unlikely(stop <= start)) + return __Pyx_NewRef(__pyx_empty_unicode); + length = stop - start; + cstring += start; + if (decode_func) { + return decode_func(cstring, length, errors); + } else { + return PyUnicode_Decode(cstring, length, encoding, errors); + } +} + +/* PyObject_GenericGetAttrNoDict */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, attr_name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(attr_name)); +#endif + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { + PyObject *descr; + PyTypeObject *tp = Py_TYPE(obj); + if (unlikely(!PyString_Check(attr_name))) { + return PyObject_GenericGetAttr(obj, attr_name); + } + assert(!tp->tp_dictoffset); + descr = _PyType_Lookup(tp, attr_name); + if (unlikely(!descr)) { + return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); + } + Py_INCREF(descr); + #if PY_MAJOR_VERSION < 3 + if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) + #endif + { + descrgetfunc f = Py_TYPE(descr)->tp_descr_get; + if (unlikely(f)) { + PyObject *res = f(descr, obj, (PyObject *)tp); + Py_DECREF(descr); + return res; + } + } + return descr; +} +#endif + +/* PyObject_GenericGetAttr */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { + if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { + return PyObject_GenericGetAttr(obj, attr_name); + } + return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); +} +#endif + +/* SetVTable */ +static int __Pyx_SetVtable(PyObject *dict, void *vtable) { +#if PY_VERSION_HEX >= 0x02070000 + PyObject *ob = PyCapsule_New(vtable, 0, 0); +#else + PyObject *ob = PyCObject_FromVoidPtr(vtable, 0); +#endif + if (!ob) + goto bad; + if (PyDict_SetItem(dict, __pyx_n_s_pyx_vtable, ob) < 0) + goto bad; + Py_DECREF(ob); + return 0; +bad: + Py_XDECREF(ob); + return -1; +} + +/* PyObjectGetAttrStrNoError */ +static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + __Pyx_PyErr_Clear(); +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { + PyObject *result; +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1 + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { + return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); + } +#endif + result = __Pyx_PyObject_GetAttrStr(obj, attr_name); + if (unlikely(!result)) { + __Pyx_PyObject_GetAttrStr_ClearAttributeError(); + } + return result; +} + +/* SetupReduce */ +static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { + int ret; + PyObject *name_attr; + name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name); + if (likely(name_attr)) { + ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); + } else { + ret = -1; + } + if (unlikely(ret < 0)) { + PyErr_Clear(); + ret = 0; + } + Py_XDECREF(name_attr); + return ret; +} +static int __Pyx_setup_reduce(PyObject* type_obj) { + int ret = 0; + PyObject *object_reduce = NULL; + PyObject *object_reduce_ex = NULL; + PyObject *reduce = NULL; + PyObject *reduce_ex = NULL; + PyObject *reduce_cython = NULL; + PyObject *setstate = NULL; + PyObject *setstate_cython = NULL; +#if CYTHON_USE_PYTYPE_LOOKUP + if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; +#else + if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; +#endif +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#else + object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#endif + reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_ex); if (unlikely(!reduce_ex)) goto __PYX_BAD; + if (reduce_ex == object_reduce_ex) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#else + object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#endif + reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto __PYX_BAD; + if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) { + reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_reduce_cython); + if (likely(reduce_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (reduce == object_reduce || PyErr_Occurred()) { + goto __PYX_BAD; + } + setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate); + if (!setstate) PyErr_Clear(); + if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) { + setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_setstate_cython); + if (likely(setstate_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (!setstate || PyErr_Occurred()) { + goto __PYX_BAD; + } + } + PyType_Modified((PyTypeObject*)type_obj); + } + } + goto __PYX_GOOD; +__PYX_BAD: + if (!PyErr_Occurred()) + PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name); + ret = -1; +__PYX_GOOD: +#if !CYTHON_USE_PYTYPE_LOOKUP + Py_XDECREF(object_reduce); + Py_XDECREF(object_reduce_ex); +#endif + Py_XDECREF(reduce); + Py_XDECREF(reduce_ex); + Py_XDECREF(reduce_cython); + Py_XDECREF(setstate); + Py_XDECREF(setstate_cython); + return ret; +} + +/* TypeImport */ +#ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, + size_t size, enum __Pyx_ImportType_CheckSize check_size) +{ + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if ((size_t)basicsize < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* Import */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + #if PY_MAJOR_VERSION < 3 + PyObject *py_import; + py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); + if (!py_import) + goto bad; + #endif + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + { + #if PY_MAJOR_VERSION >= 3 + if (level == -1) { + if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, 1); + if (!module) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + goto bad; + PyErr_Clear(); + } + } + level = 0; + } + #endif + if (!module) { + #if PY_MAJOR_VERSION < 3 + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, level); + #endif + } + } +bad: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_import); + #endif + Py_XDECREF(empty_list); + Py_XDECREF(empty_dict); + return module; +} + +/* ImportFrom */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { + PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); + if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_ImportError, + #if PY_MAJOR_VERSION < 3 + "cannot import name %.230s", PyString_AS_STRING(name)); + #else + "cannot import name %S", name); + #endif + } + return value; +} + +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; + py_srcfile = PyString_FromString(filename); + if (!py_srcfile) goto bad; + #endif + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + #endif + } + #if PY_MAJOR_VERSION < 3 + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline + return py_code; +bad: + Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint8_t(uint8_t value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const uint8_t neg_one = (uint8_t) -1, const_zero = (uint8_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(uint8_t) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(uint8_t) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint8_t) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(uint8_t) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint8_t) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(uint8_t), + little, !is_unsigned); + } +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + } +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_ptrdiff_t(ptrdiff_t value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const ptrdiff_t neg_one = (ptrdiff_t) -1, const_zero = (ptrdiff_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(ptrdiff_t) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(ptrdiff_t) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(ptrdiff_t) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(ptrdiff_t) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(ptrdiff_t) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(ptrdiff_t), + little, !is_unsigned); + } +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint16_t(uint16_t value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const uint16_t neg_one = (uint16_t) -1, const_zero = (uint16_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(uint16_t) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(uint16_t) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint16_t) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(uint16_t) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint16_t) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(uint16_t), + little, !is_unsigned); + } +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; ip) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/parser.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/parser.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..7967a4928a0b908c064dcc3a83522f9b76b14911 GIT binary patch literal 83968 zcmeFa3wTpi)&`tX0_74?glIvL00oO&tX8yG&<0vKkrWCDqH-xB6$BI^5fH>`8zCN| zIO>c#I^tbt97i1o3W~IVTm%7eL>v^sYhpn0#?4Fq_g(v(G)dEre&09$^MB9(^&w=R zz1Lp1z4qE`U(Qa+mCG&Z7K^1RKGCSfQjKr^70UmO|CgC&v9#&Drj6y57H@T_PV>Cg z<+5qh=Q?N4x#8M5lV>@nOuqj58@$e|r#k2Ou6Itq-dQwav~$)C*G%nev$f1NP`^Cu z>>G}@E*fBdqTcrge2eG%yu|~*$9MO|>ia&gYv4)AFC6%bd=DM?1HQ+PDwgk~t&0aN z#Pdx)&p_6{$yYS+n0&uFKz$F9=TXzAOe3v^Br7epSgyIFnPq6M<7yM;h^4EuRg*TI zE&Gvky~?dQi0@2ES3nIa-Na&PCRuggmgOj=a`D&1Qicar$^5GSta4WLOtXwfouBZ1 z4J*%1vmEC)P;6<=gz*RJ#5%iEn&k{LFU5E68EKY6Vbmx*VzC@&!#D8P*E@B-7iFOj z@E=*G?1mgj$)6M4^qq6fWbb5)Wut~H;Iv$d&&T-0{T0HT`YJHXfzwbxMu@X_JVRo0 zHGO9*K#`GxWdLqKJ-EWYbLP&Of+EogbOYsDEJdl{rp~+pfJ9}fFyMyNgByg>|6l%T zf$`ZHTELr~dAU}3$f@Zrr~UGpVttFIzpv>h?QJdgwuPDaIPuBFrx2e~e98ctOj zPYzlv?t&xU?wUT>sReC+Ifoo*Sx8pou^Ms%niG(#0jcSZj)T+iwKH@|JgHrZlotLA zObevOC6ZF8GcP3Sx#NHj0`3ILa)ol;Ah5oEI%^uNhZH_f_$q}@OT-tLtD$xdYLoR- z4c46(5x+*A*c9Ry3|`CQakod8f?7($aQEbOelqU)K(PIQ!tF3{f8T|;Gf?s}N}z^3 z19hu-)P)N5nDCPdby+g%G9b9oKy9-9+(2PFA4Ovo?)O|u#ebVdQlgSpYi26kS4M_` z=V^(Em3}K+L^O9AbWo`D+f3o>O#NOh$d1!A`mU)`$R>Jp+ja0-XzbCjqR>~jSS)!p znm#@o#^}w?*D5zUCv5<|*(vE2k>0}Dpr^rLAN&Z9G;6)Wf>e@aFJx(;Qi^ozEE6`7 z()R5h{ev;C%g`0)1LGt(NG)%p7AVRt#bZ7y73Y2G(hs=37M z3CswU1m+$n2`t=OtpB9-cjelvZh_r<^aVNYD7x76TrFA*?yTRyl{e7+_OK{0l-+Ne z2{oc#_j{2=`iN3Mvd=!o$AT^Psy6Iq(KNUIfu`SDTC9JM!dEbUXu-=fwEj(ey)=DN zmge8*?W*ZRGueTo>6(6=yii%qG`$JDfa~=%s!t!9p%qv^18(1Vm%d30UY4Ds)gDMM z4i0Ie_1Z7}nxidsYjJCHy5Z`S;nYJiw_{_DZw+VG2M# zI78F7h4Yv$u-1^s4Vr#=rhaLrUR!w}IFQXGbUmP3Xwvm4y7?qp=+@CNGqceVugo}F z>-04R%UMTjo4EDen!d%GQJlBc6@4d?j{g)_cK?mhXwvH?FtTW5_L@Yklcuc zXSmk(V@ZE%sJRvxmjy*i%k823BI>3rX~V$GP0rBnI&mkv))u0wNALH@Vaj<~7pEtt^qce3T9VCsMeU1^#}pP4;d(_hPemTjWHlD$H{AI^RN-zEO2H`6VAyV3A& z;oGAx$}ZFVhrMmJ%2^g+bPO1MD>^Edy4OAE6nWc2Yc^Bljq_dOCv4chUB)wWD1(ii z#5fi$MYS#L_^s9ip(i-M*^$XwWsVFzg=**-mZKHe_UuEm_tDs0@SMtl>c|%^_EOL-Abw9oL|wS%w3fm}2XfImB^Sa<9Y3_| zOa=v6ahi-%V|z^>m1eIfip)Z1Ir=c3KFNdxTHqRry{f~LO*D-FGREimavBEwO8Gtm3&#d$S( z=yKaar3jQGeUbk)^Etd^9xcpl>TRuxA1g<(9Yfa<#FKji|9(QMs%fC9vuSc+gz|l4?J1W_ATtaNZ*7m^Xxp1B9XJ}^|_?(1_e!J zlX1+DabPA!9Q2jKc>Ab4l!GWMmm*j%1hl812Ck;RE60BSdKynI8!MlURj9!&IsLos zRnw?#-Bv1cBJApK?T4hV3s4jdgzWwrZ)>62sUIFA69D`DMM!uca0Cgc+5=~1+Vx)4 zYbv-976okK0zd>hon#L5VTBiubc;HgP!xZS-TzPN*gHcbCz1=8Bm8fT%gt#Gsl9x${YO-NUSzUDhqgSSzBD{=~2^~?Tb zd|T)tY1QLsRiAy`9c;NUO%(GZR84Y%K=~KiQ*z_${VoexEUNZbto@Vl-|ymB?mp&z zF1aJ8X$8AX6K_HjzhYXPiNE~rZ#D6~uw&E2KYcI3#Ai)5OuRKaPCXNU9Wxy3#x`qd|iMV%4$Whev`hyR|6)_kzpwMRgu0KCjJKIhQHFpZ)cm+#9^Gux-k;K z&XotvfzOWr6My*c{144DZT$pCb+lMZB z$pvW$Sdrz*@aPrGfvE(p$LfmiiZqKl7Lan_c_Sb=?g>1Z{USg(e4XOa2k!n90my6b zvvKc7VCk~29C2yXF_V?_kO}lx0oq5PmIlzUsAH%ANmNBlO9kjd0(~Z)(R$`?U_n$` zjNba|1JiY=4B`@)dO*Ur$fa*)V4AN2#Gz(jn#4PQRXgOCtN8B;EX zA2dN?6r8eMN&wkbqTE&`D#~?9z|4NP0v_H~eZT1YpP@hBAbqc!84{0`ka!dtQbib; z3n9E^47=H*8z!%ty}*Nr7cuSUuR)B;jk8^oToWfvyeiH|(my7IX6~#|KH?31OVm;N zHjQL2?X2bNqoI)SL*NM}UeIaQE-bIv@7tWW6%R-7V85>xacDuOpLQ@^(`rkroxWBW zKBJC~DAkYqqYE&=4lFqc=Q9SV#7@VE-vm%;Zp58zxzKt$c!YFR7k^?su@kM?7FiE~ zhRV8&DX`c5^~;G{ws|f!`&`??TFeSo2ql7<# ziIx(6$2%1MVI}ECkPP{XMt7HR>3Nij~J1HNA*}wFNd9&|E82fX-_PyrL#* zn7F(3(=aQ^3QfKd81>7u^t}}~4~LJsBc1h6b?I+Gzy7WEDjzd$&cZNwa}K@xa^Ueb zEec$hg+b!)=W+;?;56qvBRIW;d3C{QE*>Q~JttQMr~P^$q3L@(`Va)CU8rodxNf~x za7l3b0h57FKM*i3IGw5t&+ab~PqZWS%4k)Y!6^bqi@O)1eK_scvR8o1sN;Dk!x(4I zL1a{nxzpO^&7npnQ5g)qz71bSoU55}E(kOh=e_~Kz(VNc zRj6ykxE;(vN{zHw zOmcEXDTn%*A-#BNT)(~|xnGl~JI0fz#2M1sCxJC$U3(Xi>;1Y3+0V8&tQ<{WLJRN& zJ=r;VyFEejp=0gYlMNMVk|;z1-p#}K5RHK(rtX2#Of7hyFdwqP@%w8Q6krq{=Luem zrPL~EFfBN#Ow-dn!5gNTg1Yr$2n{)5;en>vS|HsWD7HlMG+im8Bseuz-5s2O>R`xS z`9=%@Gjf!sIL|8TueyM@1(zorgVDqutU-`d4&LJ(2_JAyej71 z`UHz`0%*(`Rezw6q(j~`|5mRpan&L9P?logU58Z=cKh%a7&FEy#pIvf!~-n+D`c|I z>Las47jab^Zpgk4CSqCJp$)qEGAXxp?wbagju_pt1)gNixTQ}*w_J@!>6X)&z%;Jk zBm$V-@=n^mbjw|mE!}c0lYvf)`4!hKcYr_eV)v&B13N;UN>ybteOT1@4i}Uh{kFm{ zAE9?@y>1uTJ_~F|rY75}|ERs{ajEub1-}Y9H3bEG)m?murhD`a#u62R)0?rl>d}|d zFP1>@h)UmPRJwsGt69)(9U>FU+Cq?lfI~3x5n8k2dJ0yMl43XAdO!FSZ+~|MNhYiy z>DGBH4J=_1qzdI;fjK6IJACpGIDfw?LJ5iFH4WO3_e zY~j}5K)6uKaKSZU(!>c@Va?jw!r&#bATE|?vT(H8_HoSMTC;B3j<3+X%fP1^OPjBG zk-T-H=cyP+krHKI^9qWw*wmY||DbIacy(1H61RjN$6Q@4b;ZXo$@IpPUh{Z*p%}f) zRP+uhdavyjdi{i6Q_?#xB|WUCW3fEL9hi|BH%=CM^f{S%hxHFj^y4Vb^5|b``Zt)I z*sB;ax%Ev{vs0@)j&bcScN@;&+> zKrY?_NVup9LBYrjs~ypuaMkv^o<^Q0xJ=4C2*sUR(9svuDO3(!03Qz{Y`!Mj4&{&2 z^oIp3;&WI2lIEQO*OuuC+A?4}XtK$hh{$?1Tra&^ z;5b4vL47T$NBU^`aBRTD?+*qh=A%oW3%p*e;|+(#tTHDKxH8ZIu%a+q!`cG&vo;o* zT_G-X7RyhLpJ4qt^mhm%-IXW$*q01|@j`>2?v6(FWp|D{2T$p5Mh}8N-{3^tnAL4l~F8xRx%sp{we_cAV2*`6#F)|m4vzWLJi5^T$ zMxqN7<4l+lNc3XP5G2lKVjvRaIdVP{y_x8RL>?1ek+_J74oFa+5ri7HA|{$6F&K%c zW9tTpgaOkDQys`I7qndr*Scn-*f1uXme9({hOf)nfOQSXy*;Oo#d1DAh4^^z8Hdj` z_{_#<5k5=txeuQe_&kqKH9i~h*@e#s_=NEJ9v@3zi={O_S@>k*lZ(#)d^CJ6!>0_N znfT1drwX6t_&kiyQ~11q&nkRs@Y#ybZhZFP^C>=u@i~f56rT(jd0Tus;uG`FqkG7B z@EX2C*A53kb3BMbY&9Ot9);}W@gO}@`t%v%fovskfW~<6yRt^dgTacPhxCq>#L>GD z2o*g`DtZNq-t!o)(J-Bao{R@wQ_}lSj0a26;C17{&FaY<4^HnEHy&KS9+1CbJa{2f zjR!q2K+1S9m&#~pJUIRq`LKBd^1n7b`uEf18jt z2L?4)^%t%he_!XUh2LUPbQ=(%XD#9KAbY^meh^Ceyo9(OabGeTGoLRW1GHTg>rN z#cNz&xGc89pkb9a7rW9?$4OWX#`Y)pWzNF%rOTlsO~)Eu6dOYYCw-W;Vvf&MU&IWN z&pi6{OpiV}gA?X_0;OZWr^NrMx2ZeYG`j?wy+{-z1{yj)Z=W7PDDBoq%ttUg^EKlA z1{+@)zP>oj0Gx+;X6MFC*%3Fk3hPc1VXC|%bT`@|;sOWUYJ3Qc`dZ6oVWl@6(vXx8i6t>9Q9l9CHjI@SiTM;gWX1dutSV~T{e26}7_g{*RfSvblJMe`tE_ZX4 zEOZ=&B9P?t;&Z5+>sC(gcGX{Q)R$$i5UoW(^hpra^zXF5!^UiVJm#Rfdz@DArne_1 zi1sS3Giv&vjAIqgB89)E-sYh(gTb^lbn!&`39nCWt}GbTWESoT z8fyYrBX)*fg4aa^9I&Pl%sNWE3Av7~PI}dR*c9;?kQySkIi(IYC&Kxfew#7{to+Z$ zXBy`6I5$zIrt|eCx(v5tvl{ad0nGtxuCn)!kQeKyvLK#v**s*+VO{if7U%Ci{y1_afb3aVY>WrnFH zk{V881hkB?t}*bW^U=L?vELIIm#Od90@Ffn?9>G2A7GdE1ZMB@=-+w*^RZI>`Wp5b z>$UQAoI_GRrs8Y~x8Xb71;>4D+@|mF(0AYoCg6skTy2qMBg28vzo3cWy0`Kh+r#gA z0@q}h$9$Udmq3^W1lPi%{*tH0?9ZH-bvjxq$I-0`n?=4PaQFgxT z_1D0WNALa#Ldqge1JR>sbWPX`=}$EMD}KXUrdalYcSJO>AC6Fp$ zdY+=!CE_XC%M8<7R-$i5Ul?8^!wyKgz<6jZIKnC&=eJy@%i$hZZs;DkLQb-B=p+sS zH@NNtuDPiTF5%D(*3*H9v(3*SnOiOT(I*tbSd}xFuNL;WU?!`30SK48^woezNO4Xm zr4=`1@F{diCm`KCXdAK)z5u=uS_yqT220=K3uHb78-Sir&K@YP4W~lIEd)i+@dm=) zp6d=glCmIaPMhQglE>@Uv!LimkL2vw>TfanKD{CjOQF4Fh1FEH@(kmCg|dHxwn(Uy zC%VRYbaXLp>rZ3jW9n_5ag%;y?b0-T|*``VT~Bu4}%ziQI=>IYs z!}0M;_~NA4IHKa#Wn!XcFK)dMGY!mMJbF#!vl4_^C3+cVFJ2sP>fJCZfN? z1Hxr=%#P<@B$2(q;j>|QM3`Zj)gC=4n`^j$l$aI?o@lZA3lJ6csw8Qh135`AfFwl?DoW_`Z=(dYrKyf$#ikAn5Jc1H8oy!ckirb* z#I|wT`x-_Bi?A4v*<*#+g_=yIp41^cxNRf5Z*qhX7a#oA{(Z#@Yzapbe*MS#_x9&W zB%yx~a3uHdtQ7tGVnCsPA6gsNzkAY-{!Ra`#OU~2`}c);(!ZTp4@&Ic7yQHM-=rKm zBFjiA`u86OCiL%o@Z3=UKD(}ePlbg4i~9H3i1QNq_d(2e>i6$Ffc;>R<(=qt=#>jSm{+aoO*EZ7;BbL%ZCW3k{9jz4>1?*KBVZfSf}ZCRq!EsRt^*TQ~iRZ z(NsCDgsMppYO(ILgdK0}l4s?Q8*aZJXG{!r%5n#0;dKKnqMBc~(vf;b&H+~A0E-#; z%=$C%RN;%P+|7@jA&nbPf5UoRn`hY9tgD{p*ME4vee+W!a)c2x=G$MvJk9kwP0hD8 z%(o{zN$dX2^X)&K-^hG>GDgW?G2i|L9AUnlw=!|Q&3Dg#%X;0b8NY76y|9;fiECiw z@Dj#+yBT5{S2am;zMYT7{}l7>gZ(H^;(YrS4EXit+dM14*!-;1{-6M^6NjaA6QnmA6NzlFn$H8{l@*kTRGyI z`+;|YQFA}=)ZQrIe&9ctnYbT#U0;-OKX5gsd7<%r4DXa`QW?J=*bb`;@%w?Lbwlnx z^s`^PA9x>#{ulNGi_a3T(RYw|4P!qr3lY;A5_eUTn~()t0gdbjK6b8(`i=d-L0l(+ zJ8?F+AIS4Z2rw8CrDxTl{$H{mcoKU6$)Ux5Onm-tKQP6jN@M$hqg@ivdyIe{D{z7N z2M_g=m@Rb0OjA(X3{G}aJ%XiGz5w3-3`U{?*GBK9%t|qt_Coan4$L5;&$3oMf0ikmr_+m zG>=#DIGu)-$)YjrRQA(SZh)$2-W3bywxgLPc163aErNkAc%*Z6F?nwL`}Y);>WZ z#@blL+M|L~pdzIvLTT?+KtOb}1Sg$tF2y3H-wdnnVS+O?CWDRe_ zTh`qotj#2A!xd{UA17kb+9gN|Yu7WcjC6>vF)p zO4i)4wU^^r^OKxz+aa11*1l7$RT*e-YltP{j5@a8XRsnKCcxNEH+ZX(%}(sBtl=3P z{N2jeP_%;ex8U}fUEt(a%*h5mMRd{Tk!+mn)PlpEp8nRe@5OQ8jHsh4z9TJg3scmw z>UZSkIM#lBnd|%_?o$*OhYuvKV0dS3Ng$s8LdThbP2a;_ys(MuXmEB-ZlX!trSs^U zamtK`OfT(;bLK#f`Lu5bd z#j7-UzYAmMkPNSmqLyiO9~nD3&=#WtJiH+F0fUl{pQWqhgtw z%AAeNfw9ayl{p`oIkC($C9|>uDnou|EWg?Jl=NOT3Ba4R{;i7#^5i7Wzgl-cLSS1r z6yja7*Z3s6q(N&2l&l4C3=U(_D+1Lb>ezM{nqboEGLXPIc~pW1(MxK4?V^rn?nZd^ z&t{CYa#0@XzIwKReSv&{ISDo(>Zl;t2?6Vea-4eqY6Sp-wr9{vp*fuIB(1Z{dGx}o z@HQjQpCS=^UlB*T_4kj;5$H7UnObG_QnbFs+y1EQc$%+G)bTyorH6Y`jA9#yXD#aJ zA;QW#5j>-eV+@5j2Le#s_l2v~(xZ-lst0(cH<99ty)Y9w&&*x%bxy!Ss$GfR@r0PsRfgHCBO9duyD z+qmSCGP9&Cxn!DIGA+4ewplVexn#asf|u?RB-Ja>94u_F1zweOV!679Zh4_J584LJ zEAKfl;Ll)0W!^{nz8j8PccWi^OLR83zAL(iExV5d487UlYE>>y!7*2KR+sxXl`HzH z%Y9JgimvK%D^;%OsfB^pcO!6$equS3kRy7D<&+>t^byN}zmDl4me~WDFhfyJmJAWN z+>e(bVUhu>z=e}q^Z;F4LY{eS(tO{<+Dpt3ceFw^fx%FZwF7h1A?T#H$aU+_%M4`& z1{VVKD?T;=x?6$b$j)H8xDAbfKBGWO0ZPaBKqH`w6exn_!Q%irs}azV3bYKMWdI%2 z2xt!lIt`$7ou@Sd`Xf$0Ns|Qz)1e;XV*?u4r9kHc>wJLLHUj#TfT~80UGBNO;R@q>iFC<)+)#vLdA2bV6f|&G+_g-Nb`P*;pPKS!Lag_#D^GGdIPbDtf1t; zTF~)1i{S)dfN#-tkCPXqqmDf|A|!zvhWjnzI`A@qo0)P5e=l#iH1F3z2xG5$Lb?B_ zqeyBVkw9TFGlP!%g$JC`tB7Iso{MvSD7s#XaPPoB$S!afA-0RdU5pohmNKr7;F28M zYy#;J=8GjV=v48LThwtb(FPquOfntnk?Cxb8Qut)U9b=#)50WEVUSsg5{y%L0-0kB zqp}!Uz zCQqV<_f$ov!lZL6GK;_hNF{15x}YQ>vNUfarMp8btD}N&e1+Vwa>i^&x7kd_s_u|g zp4X#}-AExWh`bRWJ~BSI?T{K(tj>1z+-pSpsJveWX5vd{OmV##?(Uf^|WIE9(JW(z7C(Hj^7N{28>9jX}TT~fl7g~v5H zBf1~Yc%iiA+HPlJ9<;X=s_WJlMWcADp)!mi*tR;1t_j%H%nn%B;1P=RwOo4^>pY1% z2(yE>7GN*x*ytA^-j~HZ083$6#+ri@%t*l zc6SW0gn;KNHWx4#?`^9nH|lsv0e6j&9zo!yf|Y>Ng|@Dsu8E->NvQoTsTb?#g3>X9 zvjyE&!>1_NXbyfwOQQ+c~TUV;op)xppG+|AlK718z*X)ow@BMAf@eb9Iw-fE1VcH`~H3UnF;G;604y<4Flsn9q1 zT#EA=r9!|B3w2qa+-#I!Q__UD#P8fQ~r? zz!t~PnDl%mTy(%-}0IB)-kI56tny}ReqjXzn?1q z_A`TiK$VMLSl^+_cbnzYRrwqf{}0W@#y|elVp-jUjzV_~2W-?)r~m^d;C29FV%VRA z1J;wo7wpsuaW*pl`6xpW^iXR@76+}PpFl>y+Fm{RpO&XK>glX!%8noJ;m#3q6iaL%|(8%md2R4_E_7W(20^QdmzVPAx8Eac|QegcZxwaQs?^N9X z$mm6Pctm>JRKSEXPE&Y(XvU&#p_~rt`7=HTtu078(CJe7vMv-cZ5xRk{RvO@O#J47 z^%F^H_~`>%NRs>o1nXfWzqMy-x!)rH2p)ha@PYIzgZT;&ftR=snPC1YpcUr7SIobA z8>)c$xA+~f?iZ?#V`v(fqJ}!5VW%o)^U194cCoYfI+pj(3!dUOa`abtpWS0S}6D zm5d{WOWPm-MjZp7Aj)_yL2yS2%0gvEyLM7}{dEF9K`O=yP`D{a;j(m5Sq~H=Xbzp- z5#IspA4#9xWh;QRo&^b)p$Bb;?j*9YamXGPWKN49JBVT;`w*rCWX-^_AX}6Y*`tE2 zMI5pb@yJ#f$d)T)wI3VE&aRJaHJTHAy?zVHixag4=eJtBh;Fhg!FB6J2YF`nd&b&a z#L%rhks$+#bu&}3{MC}rg%fM}f%t-Pe3Gezb!tMv<*I;4dnXi}sS2DZxHqA|uL>}I zu-y!?aKQa4`266FwPKl8+S?=LF(_yg-Tl&1GeYITuw#EZ7z6n zxzxT6gF5cvqx3zR5Gt`5bw?jisz~VX32;v*?hOx~+ zem^0%rlmqY-#~sGeJvjOA6P~14bmN##gOkt3it4t$Xi>$`GbU_q+)AaScnJ+?12FfU2M z{0uQ~BQv_A9blABCJW}s&7zZY)@2g&bAZJCZFg{CAZcxphqbCc15kJ=F(ndr_q>?* ztC`z?h=!&BJIHN>Ah4VtKo#-3qGewPpKV$D3b_g*6?I&X0^)LA--lf2cAt}5cLE|Mzae1c>G?0TK!2Ch}Rg-ikUN{M3V!jel&f2fy|pQz6`W$f?ok zHT)e2PMMDF(_L=~`F ztrg(G8I{$~qBSk{;0$COtCR=cS6iii`e#svzLa_XtqW!zyWK4HmT7vWXbV2Hmq#zm z%-hQA>+Zs>FtGF*-1(pBJx_~bZKx*0U9e@**O=*c6pE0w!opO+dR#_=hWuJ9cn?Y80r8zU*rbcC=T%heuoyE!g+j@7l=6;3!;$x86LTRgmRou0Fgqbk#43_NBmSPK?2gvDE7zkTw%M0mhi6=NjfFGJ zckZ806a)9;3zhN9AGk+x6BPE9ec5Hd5YAYJ~eRYbP=UkT&4wv@Ph@}A+oTY zv}BBzTQkk|o1q99~9 z56Aqu^?D7RuHcPDpYsm#jfG-;owX@LvB$m1cPei1!OT^z8QB?H1yc9}e*i&y?&`+ONdBNNJ@9M%6ceN3+CwK#|M&>4rpYYondG;`~8m*00yhrGh^NgJ=My|DAY%`ny5>RkyM94rD<6r^NcT zx#hA!P;$FIiiHf@?*Ruf^|rU2G~~OI@|}cyxFxKDG-C42!IQ{`(*+nFe*_!m@EDzg zbkLCl+A=&|!ZKxTu(}xScn?xvemJU=_!%1~?)b^THU0Z|P5%|RTl6I5H6{HF4~C=< zK}}J|!^lW2sf?CN%)bdgd*j5s*${I8#C(thAm)5&MjcN|%zYHIJ*&dmFbc?0V!A+B z#2m+G5wHHhO8MXgF3Zm3Az=u`_Wc&K#vi59`@YkSn?|uxnIBsG6C6L+gE=%$#3q83 zbopCdBl%lhM{6_q<9BGWZJ`Y?{5a6KpYg(h|3UnPE>n3|@mIRI5(<~TO;Ph^a&>N3 zT>XTH)f^S+y09|)mm4V@m)Ctbh=MGDxg%%arMVrXib6AQYbT(+JFFEhE=Fp?CAQyGOCZseqF6dpDiBXVHsk#QXg!P= zvR5yoG9Oen%u4g`_MW0e@v~-<%^WEU;0N!}ljWp}JJ80X1L9_A@JjRrj9J(>(E@|; zO!R?4nOsoEb#XYQjY(P|Lai;Bobc7&`Y{Vy1DT13w-Ek~77pBjz8e3Xqu5P6qCjbR z;vivrmert+q>UOsMvA8tTUUezz zv(lLI_;{p+y8yQsvWKBcCN6Z$^qu9_-;O%&nSqGnI9Fn@?+O-RbasC>a0qp%V;+JR z5ZnNQTYW3t1xLM?F4uIpTLkPtspiNDC@&_;y$a>kCd#)#TA|$My-9`pM}4c%C37)7 zjLcvQkJEZ>(rS<67Xw;vj&!Dm(5~CGUOTkf6Uc136Z<`2!d^8GotCd&q8P7l6hTRF zp7XK30m5W|Ek-33Y?N{clVE2eg7Tna8|R|B?aAvnqp~W0iuvd@(~WIMwrXM>-8N4F z&!Ik^9!Z(dsdKz6wKzBS!VDbxc50C9kb3iJb>B92#^nA&Pl0tkgz~j_ z$rwxTiUR|P=FT7s7@+dm)y-dw8VXSJDvdQXKn#%>jAl!=Ei7CgiJLE-Ep3F=4@j0g zXXivFJ|GEY=M{WilI1#b#TB9e~5U(K3qiPMXldo@9O&Aw{AoRe!0dd#mLlcf(U;;-! zT>3GW{&lhbwM&l{>&Im7mOBkiL2G9l0yOj{zia{U$Mf)|I4=kY{17OCs*bba%<n75cM*KI(V{;+dHLlz{o7)R@x+^AWJ(y%AWw zrvc-ntwg*fbSru*S;YDf32BnOEu9!Y{4mwU?f`sWDq9^u$ta!QB!Kh&P|tIdgOZUYq1<V@-%-_7Ft9$P}!!E52U#+y;3*SL=DjieXDX=2#M%mioHicxYQTJi7H zHnh=8cdQV_!{5RE;QRufZgFT2Xz4XY{fjnd_;51#jLqSP)7Uz{fKEvfV@Ychv=D#% zFlfugG(PJ1^CSXr;Q>RU0Ar*NBGcGtI+asxyZ?D9lDT&H5v0K!u(_{!Bw1E?9g;|4;wsp5%UPWMr`PnK33Xs( zYz=*$fw-h6s$i(_-B^jwlL__|7c~&MpKN_mn+a?Z-`V4xo&1RFC)aqCme~ zA=R%tzQA4&d=au>&*H9{{-#!Yu&I{5Q}!t`T}N;POAES>*xO?6P_XCLLt6S#S9BAQ ze6b!9%sd7W&Nzkz4RofTk%J`>o{4qb+L+3hj{)rx7LjVm<;=^%%jbC0Xuzm#=?f0z*%o?^5zRhkyXY0||d$2NG@TRY&P-e#k z_1G?sJ*c5p+|ou>KKVk39owqPircDc&1Ghw2r}kTI^A`--JD#*nX3Dc-&so*O5M0D371N*4uB|!Tl!mm-Pti+PR~6Q)NSjr{E*| zve}TgnA;E-g-~oPiE=523U!IZ4P~ArRVpxkuXwG;IxeA3m?ES_I$3pbe7GPZPC%0=p(0KEkIsf zf#n&KI5kf-9!z^M-#2i$rK>c% z{ebqqP8AEZG_Sq9a>1yn-i-5Vmb!-L)oge%O?_7^a9d%P>cMPFezSkuSB)$!vaecS z?y5YHfnR;CTu^A4#~%Pzo2C^DhFiQHh{4<9==wrmQy5m;I!91$U-NOZIb+K?(6v+x z#x!SUx0rh>x$>QP)K${NmsJg;MErunqwAf%cA;E6qSEQ|dn1yMu3Cr#0;kth9!QrA zHUE!U|Mu-7_F|8*2nVqqySDyZ?EU(I6$lI&?;{g6K}L{{=}Jd|rMGL9Pijo<|#$2+Z^ zu8W#>^j!q%uF4;qd(Q-URPh}EdAzZ*nehY`2RMUZWCwa_0l2o>x-3N+8z;2_qF7*Y zovy^5mA)2bXBO$FlqePDh);t=IpxdYcZ=*RTjv+&AT9)cbB^YrK5`dTjx7g zN29b(#IjopY8Rg(-D`tOueGmw^VnXT*Z8X3mHu{K&FU}Gfrquq3*NT>p$5|(^Y@=+ z%p4PoT!YVN=W?^@wnMv6MR(<3hdTrARw%BhUa1pZ7aoJIMp@tvllyhl2 z@RSky{)8+o`I`|!A2N<{DmFYyWn@O|xFfooYZ60%vtluRO}Xk*0o)O~3K}ji3Y3@P zwQI)-(K~H{%G!%=>uANn+~w~@T&cW z$QPT2j6erdgmD-Jk=Aa^>P)(AK^J)O=0}?MbfT^5j2;v61J=D`DC3A??a4D2h~Gc(HVi?^2BZ>TM|&)u6*uGtrF zz>2*8PGAA2O~TKhzDe~}h5B*>HQiYPYVPR(@!z291`$tFtd?(v8k&TgISlo@N8y6j zL$ejv9P*M-ml5@4f*Nt^;#zxKEa8yV>sS@O3co|6lruspr?O^O0S(xjPe(3LZ(&9Hx>my(;g?fftJx%xGhK3&I&!LOwdkac zYqcn)nQL_mVvcT*lbP?JM}+cEMx*F$cE1;n4sBa{Gun1Y7CSvoOF6Z`#2obL{ICt) zL3OjN0XA>@0g$5VEWsrLT#vLA+pGMj3J{;XJJmLM0WZuUj-@dX{(6w$rhk5ChTb-5RDfX%#;MOa{ zsIN<+slDoSCg`=U?kLOvsTaT4X}upi%Ix$s+l1~D%tdEq2m0h_!+o=A&1obAw6D|C zW0B63Q}^$O9Ryw3 z;X|2qB-4PmqQGPK??fTAUfqsNy%h)1L{VNcLs72h?n)|1_>9H~zbJ$=!~9i9vz4RB zqt$8ls)uQHBkX>UVnO6xZ4?jpo;{${?msuKXd%)S1y|VpXQ)i^8sUy{xaY7SX#ELu zZz_u&ETOSVmXqb_jkJ{C2^2w>HC$t_V|kE5>zLd?8bT5(({f9;@VHr>aUERVTx2dD} ztU?<#lvcl;Yl!yz#?X!e3V7YH9*6dJh1S_%TkIm*57AK@9MO6Uw|&Cr$DzGJpm=HrzHLO1&%04Sox`K!&^~Jj(#Kx49c?n8 z*j_b@-@}w(&N#siqB>gWL&WOr?)7aUmmJ*O7zes=&?@|Pt2)6xMjln^GCb5^yZ_H! z>WUvWi{YW5>AT~Ku0)YI)tgmjbxRu6{5afW00EY79(ok@EJ+x&++o3VEj|$q; z!n5PhzN*mr41=t%gxN&9{zxNAm?~(q!X4t!>I&`0*C-`elerC6AcvTzHHP^-!Q3Id z4jtaq!*GRpk)elr3?(fmLj-gM1iq%GW9h{}KQbiJChg-yLg$oQr-r0HD-naJTr1h`(vq=yH^VZKvgo_Bdem=743?`aJ4xq`Vz zI0WN0+t7zR1jUu%%e+%0=-qHeU12T?Ay8;cLu8K_WIHxS_B~i;&~;Y$#yGOy(OQGn z#SIF?4I%c^nnR7K>LI~=M)pUg<*WJL1PRU0jB^j$9p?X;#G>c?`lQ7-l!HVHHiP=%SIH|ONe(2e+A}E z%tICCVMZg@cQ<7Q=7Ei2{;Crd)+Kyj9OhzRHXQn+6bs&YR);#mQB+~^7)U$G?jIFb zv2kBXZ){Dn0Sus8(arC0W(e^JIk+o1bIz8Mij-yKCk+>T~F$i1Y zh`JQfS|eF^DYDP&!0CU&R+zx6W6pF z+P%D+XzBd%4Ov7f8ySA=>Bi9h(iLkgrzmch4snaE9YCHe<8kCR$vv(zyc3XX& z1n^=G1vu|~ux{}yTuod->pgLK(D)$x%4PYbnQ3Z3IUl%WWH}v@%V2sLFqJPCq?aIR z*08iTYBW(byln(}m-2g&ohEZ>Qm0kL3Fo}_+8PT?42W@W#S?GZZ{OSn(wsQQ?tduG zTW&(Sq5zqGl^M6*{upu;{i^)ZwrO~ox$<~3`w}k!W$pBu4~(@_lls)S8V7J1!l*GQ zR-+XS~zQpIceM_Q&?(!8J3 zh;eZLVpQak-VXQ!tXRrH{sG;*t^t?W{TGnDfxsE#a9O^kjp)?-iL?M;pyk*;oBtJx zcK@mTti7{ZCF~tncSSQ*_kh&xYt%hos(r?4iSjM`i1K--#L4ENY>#Eu1D!0O_9}X| zIB*xi=hO#3Pr!Xoi^ViU>qFA`wNRXMGuJ`|w&aqeF*Hx7r`a!1h zL<_rrX`IrgQlOx9?mE+FUurO}prAU-B8<`UBWot!n-x z41;?u5629|Xt2{2?Il+>)Va9@P1;*OZiM!BHGrVUcCq{U3l*XZ4zaKwb5r0Fk`lxI zXEGPu_k;$z3~xvSnFbew8{?t}u|zl6p@GWdUF}Pbff143@}ZLcCzI~~#AZZnLu3NT z$c9Kir3I0_GtzOgf5QPlWX}dKvfK4P!2>r$p!BZxsuqZFgzzn(B%RjV2_4oyB5vgA zk90*rOS}Ifl^Gt4fi|fp4f;Us6CA{Dncy2vp@P=F=uat^bAnEzX`Y3T!976sxNG#?g2|3%~!T({yy0k-=zG>ALlKvT> zul60URc&Rj8mi3dJM7idtm+4Y6$XtijnHT>qr*=yG8q^gFrmmGSuIg;@gc1k;4Nn^7h2OxJPXAT@<0}APk2V8-_#W(m$;zxCnzh z%93pQ>Gxr*(GA>YyA(vtVFIT`O3OG*z^q}sJoh5l&k)8iRJ8CGKoIPphts_+D^IlZ z;R@6Zk$t8Be?8SSaoi7rG=*v5&EUr2n`*il`5U(cJ%Q^pA)!Z<@(|P~iJO$IdHX^| zz82+`!%H(`^0lawuckTVv-^KSbCLJ~`>G+OIM%Uw2*Raqn_blw;462vswoc)DHZM` z?N!Th{)b)mSip;Bl`gX#1X^P`x zruf0$hE4G_F~z08A!fA;y;APOf;lt~?_{HhOSD(rKskce*&`LT`bz;Xg0QUT{99_- zCbg?c?J*DmHEZM=lho6S)W|`KRK18$uG`oXvNl3U`Njz*p%ZW%kpfU@1{zTRMF=)U z{pSM0u=*&*d|Lf6ejD-Yz5%_x=f@nzO_(c~UGhkadR_8$R0R5PCp0m>l{2z>`$NOt z9{jJJsMv~P+CoP7N1Q!lswo&t3m-O~n#j{f##5R+y^SZL-pcPpbG`MSDwOy{qW6y? zc}eAyP>!m6i7dg)hZ^-xhft!53?w8zIzUX(4Rwbb-arPG)B;DNa3+<|{s7K<$PX8U z2cmsUS#v3-lmBIktaqSoMb^lzF+n3dhvi zEdJLT*nDRyOs5H^NNd3ovBofP0D$l1$uYcYz%wb=yrWd(71bCqRS6;o3`x@@rYe*N z##9$DWtjTgN&)s&V@vfnYs1ZrL9@yW-&XB}nY;Au<=u9b7wod%S4+-X9vxBw&YwWN zx)U*XfVw#d_QI=cIXu4Bm4o0eeG8K8d0rd-gECQZ(~#k5l%=o^LlrPk6IdJm5RD_C z(?GuNKp})Jl*XH>OjEq+1@=HH18WzY_9@ zDWnV=;hW%>X}C7;c>|n?849r22ky*vz87h;Kd(5&oUZev&6RObKdZFalste~$atpi zAmA861g*ty!?pJ>FSJ*^0)d3vRV*>iE8%Tv9DCfP^}>}bwf5U}7Nx(>7EJ1yKkrgz zOSE-OE%@?T$*|I{Djl0F91-78s)=ELA`dWZzHhXh4_Nf5JnpdjKLKwX*1&HmnZwyE ztc5_UmWWrEgRSK)hLnbTV1^==w+$tdI1lvLsjFI&usKBu?vd`qBboN93VAT7&gFwi z^)E51OGeaDg)QSEdr$D;Y@WZxB}e(V;0Q`us2P_WxhA;A^Exi0?;d+sh$#`jlm~;@ zhkP)IRYhTlkna{yf^{JR5iz0Z{K!4Xe`KdIS}!J?(K_MsIt*T14rPsEghp+Q53$qb?C@G+)8j#1%rS*(~46#ry+KO~E~rJl(^*rrfCri$WGtRjl9FgQTl-W+kC zgHRRpE>plX?N~UgS z>d#EgM+%f)RvnW4If2sUD3(}gv8WBp{m014I^ft8Rc1hCf3qS6{=zg#??%)Qt&X8o^#C*mW$tETNDwZ}>45PG{kT#4&@Z zK1|JIs#`*ZlW6nsY*v`X!e$ADAF^;X3$JHk80#XuK?t|FB1Q2P<0}c)n_#n9xIUqf zp>^2K!W&umR6^k*7JiG7rg|<5mnIZWV&S_ioWsHyD6IA}H8}w+pI|Q#Y!M5K2)2N! zixR-v5^M><=ChE;{i|Cz!tMmPbj>ah5R*x>RVZOeL`U|3twg7oh%$l0y{81mN1ph)KaES;G} zYE&<0p*x|_$->{W@NO3NPAE)g;Q|)k#X@^R;pec3@OTymS@`X7P``(%5L3TnYClqS z3i$^s^kRhvSy-D;_y7yru3=F zUKWle*dLhkF!c~qgAyuqV1>I`;b9hbPbmBeZ5^J&!auSwgE$^x>K7c=t&{Ivf(;|s z<19RwP*}~vzARk9!i@=qe`H}>7IKd}{0s`KIkgNw!qfz&?nMedyx%aSyEa$;{8FUb zsr1iGw?w*n456p8-dLutV(N0HMlv;ysi90=$<#okfHlh6+u_`io`N(6exOS9^qH)L z5d`w9N>?@j_{CAd`JFp8o-HV@E+L*81^BoEj15Z&LL}OF6va?3-ZG+CAcpZz)hKMB z#w@eOTGjv%-v2>X^QWY3l8fhO#sGk>_j)jEkI#83U7ZA z8gr|lbsbs+^jab}LBQt;5wwO-cwF!c^naZxDtd@SL$EXA=M_fMPl2^jgu0&JJR5zvynCijQxlCal9`P?yadojbX9>4O9ylykgfTWH68;v4f~!v_ z;FnCD%hUm+;?SJOyf<0ekE!)cUBFZ|Q~6B2z|=sdo@DA`rXFJIRHl|A1s3iclv@8c zu$VKL6YXRMbGtIKwx~)SiBB1(Pz+T?4x@;ZNT$QRRq+8u0ij8vkTzBPpek;XT>KTz z?N+l=_;aMcZ#*Acu0!ONIpONGZWg~%G?A5(Uw1|bFd?G=4yC0J4y6yp`bG=TK1RdY`N zIS{$JJu6#@<`kxW#0lNl9GB}$SYl8UYT4g2-Z!jj#u8(W>%S7UDM!$HL7_nwEkI)q z|C#85)^g;-zT>rmPKxLc#nqQERml{fEa3%Ajb!QuRk;=b@H41S4UuYH`xAB|VFxSN z?#iC2=mhb*5^xd$J0ev##(x772=iCqtN+BppK;8$`U$4KW9mt!!c0BI)JIHJGxaV~ zaV;mZtV5pGs}^Jnt7)X+7m*<=CAZ=UO6Y)I#Km#iL&D)*V-5M6^;{Z{-?sI3A*X|7 z(zhP9paNO~aFxJwhtEQofpkx#Q9=(cGK-tX+v1qw<2fhXgKQ5%Y4}XC7_{c1BcejR zPX9Ab_!3_O#rs)oEK#V}p?0VWE6~M(kDc07diXgMsdq-0q6Af)5pG5ue1mLz`SOSN zS}cz|VzJzY?|bp>WqK2C62#{Me7fUvIzHhyaG3@^y-_|7-@L;9PJAxG^M=jHL;VZ) zSS%Bfw{HXZc+FzDeYeH(3ep{jcdf-T4W9_~_cnF7&SGhX{O@Y9%!$uc_#COhfPv3Y ze9i^FQhXdp7XtQ`*YP7^_^bzxGJOAn?3XCOWwzG|_o#ODfp zj<2y;?!o8Q$1RpY_?(ST8+?W%@AK6b%cJjEEHB~v_xNHgYp=cb+H3E#&wkAlkO?q^ymEk_1^&tRaAz3s1AyIt0Q}{E0>C@p zg)R{`0PF?68L$fO<$#5NrLgcnL5?9n81B1a=d%DQfHUx)0NlD0e!v-o{S@$BxWl^` zy9tmEI01NYH)Edx%mh5Yhp~3R48SvejP(IF1H6DKfVV(%`CiQG1D@NDdI2m4e6WwP z?ST1!*B(Xv0UihZJK!3?1i;UbX6<8)DS)TH#h3@M05A*S_%>_-@GH!dJOg+Xa3kOk zpnVZg{5a%C{0{+<@1Q;aR|75qJcYP#0yY7zd<1&lih2Ru3-AJ#0W8qngT0L10muOS z;hQ*u3z!dh6>07TtO6_pTnb1B41NQ40NniWdDE@fS&+<26z<^0sIf(UBCwbYAYA<^i-i;)c~x3 z<$&7&D!>B>0@ec70apGWgaLwpwSaYi4S+8Kz5@6LU~NrK$hI6hl-=?N3@yTj!mDlqQPU6L0XLWw zh}I8;>LW)};rpWz|E3}ccN@N$Ln!m-K#@PE^Xr+eh%^dv1@Q+({G$|4Q&vY!t`O=Q zOv_6~HvKsA%s9B#kA$y}WShYW_qKJFG5jPhuArNOC}fIXo_P8oC7>H9x^X>O=2c*Z zJDEmI_ju9lNx(Bn+O00o35JHEqj;utf_` zQ2IjorspG=mxhQN)VN!6n-Jo95~AmXr5nH1x&kBf^1O{!)Q`n1uQbOp z%5e7|QAN0DI_sL;zBasb=qEIOi!3%Tq_g^Ks_~N)y_29PTvn8ZQBpB4e9lPjOaykH zqFXa*`3Sur?#p|+`z893uwG2&#iAb4M`gnJL{!&^A$%2>mLOT_3zY0_s2rEG!m1)q zV|o-B7mAESxVK!;;P*@>LV+V8Q`bmxxICI;kuFEv;@EBa4ai93RNPqz%Pc;FpJfu# zjpVu!CuBI2Qu=d>rOSG5$!|w(lvmtFw~NbqqdU~ZrNQ{IbbjLt8cEm``8t$NUz=R^)g*_pEaHg4fm%0Ig>8=Gjs2;gQ-SF?Mk^Bca*)47z=(9 z1ov>iRrZ4^&>4QW5n=eoAICSgJbML<{s|B40B>?|G-={U;TSI|1Dtt!;)>knDf<7!FAo?aLCf7<{_6Q_`MH)Hn_VQ zTfVEaac?O&;dAFHIH>m+#5zlm2K%-aCJ5m6HdYJ`646U%YX*gSVOIw zeMm4;Fdh-G&CQv2!GHR<=vDDuunum{Co<*Rq<3?E1jh`>ktEY2kH}*nhJt6PmTqG~ zF*3r%s^&8$T(1+#DIFNLWPLl+0!HEAmWaN--*Dy+q)SR06luprovN=D*)j{lIFSXR~H4W{3tNk&$q`-_A@CN+=~X%(JS=<8NE&%C(_Z0V9elvnWT zT)-E@@Vg`{@wv9<_Q=G=Tjv_nrBgAW zXty{st#II_n@K47nRVA#t6@X-1L^2ETCSL)YPzj4X}aKYsQK zzE38Cxy}*Dy?M!S#eqS3YuAH6d2xR!-o}>hZ$!Y>viZSNh{QVqz2HdhOB4e>_%UkH z`)wZLv79K@1JYeh5sIKbka&_qp%=^}ob^4&C=$J-)w1y(%7z5tffanUN4z8M*?^b` zZ8o-aixhZ?H{sQ8&4u{_+sJ0oFM=mV0Q7bNKaAEao2!Sj9)L#hi&m8BHI%8i6#H^G zVSX7GLKC=1tKlg{v~Wzn&af(!1pUrnhOJPdRO`+t+E{OI~lq#+m= zeOj*jMc}k}w^I8Q^}t&^(ykF{{iD+MBuM)d44CrHruTUsG0DbHH5|{{R@Hrou1M~F zp<>;zH>7$h*8R@yRcorcf80G>dc0zDrJ*`~Fl$@Iy0>poz2S|<{Oa_R;A8B54~jQq zBX36dW=mJ*)ytr-g5m2&vMfhU{|g@0i4Wlc9MB2PTF`_kxzLOSenQhs{qMbxVU@Bb z--6vo^oP=BZ9f#usp>Xm-i|?L*D*uYMpF`;XT~AyJvZJ2P%f+5Z28l5!*^azVndLs zZW_24H8HXd{xUU~R-JwbX`e=tqo$rl@p`Y?n7J9wtb@PK$?EzNG1{2fj({JcXJs2N z{hWyVM6d%Cmjr`gZy3a8EX9&OD1HSA0}bV}!`B`TFYh*0g1YON`KYM`4%ju@Xex%Q z;@!hasI2Rla?~^xUQ{+Broe^oz~sTInWw6*JB7PUiBta2{Go7WSLRt8Y;EJEzXhU7 zo<-wfx_`0jNVYwCbz|wkHKx}=LDxBs6nqkVM+#>1|3&hhA8sth52QpgA+PRjOZ{$jH^lu}Mb|IS;=+%+^@ zn|!Rc6xkfV`Lr8znj-~wppBxR5l`%UZDdFb(_>wH!Q(Ik?N<=r+_a>eUK6*TrZv;( zk0T;jiM)xB9v*o(79ofizo!vn#ENU*4Y;n3`Vzh+eRF06^ToB@)&A~AjJ=jLMefG} zEO9DE+eOYiMd|T%Wl-h-b~Sb%LO68y@iT@7F1w1_Hs(wvwo2@hxKrXsBz|1trzL(( z;`b$XNfap{B()SBz{xIua^EV zNPLsT8owv!3jQY~ensMUBu=A~#(1Vl{7H$cBwitLK;lk`dnDc=@skq2An}mI??{|h zD)W(ep2Q0!zD?qQ#9xs35s9CY_(h3dlekls zkC*seJ^_FMgv39UctGNP5B1VhhHu7x4UF=)(qZyzth*|_o(gBAiLe^_PRrMyG#(x zuSn#lAq(WRatVv#l3WZuWuVD(G4ySYj%L;Fba*^=pV!{1I$Ubt!=#TUvbVTZk5I+M zaUm$(Z@AC%Lu?l>Cx#QANfl2LQYA%{#e2Da87W_k{AEV%j z(mR`}4{B3`LB~qf-mI>4pTFG*`fz|IE$C@NYWSKI>du-S&Q*#U2>1dC^(@j0^=RpZ z?;IAK|M}$>eW$J)NnP*o?ox$blVq@^PKKFA-(9f?c7N0EdgH}IlVqMX6KEfkJ&lL!lRvUT&IfoF&hyN zAER*~Jdr*u(f138@Wl6K=T8^c4~pbGy}oleU%m~hzF)zbJs+P4M$KWjC*=0hA{`$S z5vH*aVS3~^h}B@eDc}#N_^&uy9p06y;)2H+QeDa%CDiH;Ds4Vj*rTEWdljG8)1fr0 zipPgHnoDteLq3G5bLa;h|PRPaJ~bW+5M5W{!Zf71=l)A-vsr$+0{vgfA4jDO6e= zLB-(-U`#~?QN4=0&F>4Kv_(pTI)~n1ZoK1zoP~nIdwn4#81_pV=uNz117TdnKqa%= zHBAed64VzX&Pt+4l!Nr76c#iVYMHv!7R&)g$FXX=!x{2)Fj*{CP*hS}9GrE95^}6k zgGxbB8UC$xDSlrNMeunY9>oz@8E%8(3X0|im01+I5`!1-6?8&=FLt+nuVPbTFIOUO@wK3OL+B^;$*M;uNRH5sVeufl6)`L8G|{Iih-K zgXC^}LMXhO4=OFbfRa!fj5T^4%^*fQ(QIq2s`%Z`RlHP`xPVuwsE;CnG#hXz^f?pN z9Z3>T7j%Q0Xtu7|3ceeVi_47$peoI7uOmQyYUwcNX1B*3>L^mGwJIcopbl24RK)9S zHm~PsuvQtO{M!G5U{OI(`TOOIUWb~XXr&5oB?U`K4`kB8YYSX3=K@zz0W}oTB$XBh zNR3mG<9ukCOha~Kg=h|FIfaVLhjv4}+Z-Wht0G&pE)g%X6ZNEGOl%JY98Q%6FhUd2 zZzbK!dTBK#B;OI=*+UW!OU(YS2+x){&QQT}tiia)7ex2x^r3TYr!Um{1{-sGVRvqq ztTNODjo*f)ELikG@byD$fTt3MOd(D89TWvM< zb!a>_byduUjzvq9N$XY7ag5~K*ifs**Edu#uMgvb76*0P(V>%FafNx;=Jk2!U>;^Q zUY&@IPN>*y)+?jLYCA6g(a4M}Wt=`>lpFE*OZXrsF#iWX0f#r(q6X%uc+a~q zP>PCk5%!Yw(QIR^)caqoyBArynXTVgEsE{9`C&j3B8(*_e_O zK7uY`^cbCav~vD=9GW>mIiq%=OBoYu9|Vab5d(E6*6!b31Bu_Srt_BKqeY%yLm!Rz zMWxmTU6mMf(YU8^;ZpwksJGQD!mu>yc**i{q4i3REi`z8cJR^8 zmr5$C@ZNV-7x1z0y#yNH#}XB$G{z)zvrF;Zu%P+G>{7*#3=GlQE5c$Z*Ecr@sCD4c!0m z{)xT?tEy}1(~;eP4_k{=j%a_vbj?O%{i zu2ChX6KhCTM>vR?Mz10b?aJ761uvPL6_E2z3eTNp9<_}Ll{8C*Z`oS@Evxu2_txU^ zt-<<&n6DyI%wS_}0NRKrj^iJt3ld>$9Z@%*p)FD=ev(=0y=e@BvDU&s7C%oWxlsD} zh_O`4IqU`{kioOj*>G;5?gi0b`d5SfFi7~PJ2y>I#^g8jACDHFU z(aO>0_G0co786b9@`Xs|D4pZ>IJ#&!pMK@54_u=5qIN8b@ckH+JSK-6$VK^!PE!#( zE_nJHyvIi;kL4fBr-9~eM-yuDP`i~a7OM)5m9+3glhXlSnpk=CbdWaC!KEELo>ux~ zG^_H3X&t3p>lGSfYf*ZZus-M%i4w&-Th%s4d_0$u+mgl{@lkyRu@0%qii~Yj8Lc0h ze!-HUib-%Gu{MVs>j_1;rZ03Cd@l)~z{hOpnEA!bBbpzr)hXxX#`_U%KAX??Y8?sn zBXJRlIuaosD~}D}WyoI%mB;S`)VQAgy;v79YwILhgogiC@@V`=TGw;~b7lX%3qlewmIp}cOzO;o471^`0#<&bI%x!F*a3&%Wb7DV;u#R*JfQzM#(H1D5v2^=DS@yq1TTAwu`dJPP-&|r z8s)zkE26ck{5IaVDu}-d@mg4Zad9+_2*V!EVcdg(siGn`?Rd-oG{_ljf|XIa;$mkD zW;Bc6!MzCNuWZ24xylNnDT@!oX)v5hhzqOXbe8xqPG^k^vvRr>@nM{00B% zIGrD1Jy?e<3dmi1RNs(C`14o$JfSx7lO5awdywI4*RFLn(}eASVi4sEgq-;`6+E9~ zabY*{dh}c@#$bj6Ilxmuabbp?Cvp8jmnp{H8hs>r92eIVhHSnhfmNIQadNzz=#PD+&Yy z&ivxJ#G(mdTVi2cCJMjMW5`NjS*~#`YaVb(x_|1_WR~_?%776Cd>D30<(x4+gH3-Y zgH3xqlTChcJj)8@GP5g(8Rt!6J(F-B3t$*Jn?WC-poWqr?KWEli6}xF3WhqJe)FQ^d~nZ z6_bojkWrMwjB=nXD2E{n?k}egrw)x9H2IB9$=0Oe8RjHrJ~ELF%*4K;d>j^0ld%}(zBhy2i*inTCzVZpJ&k3&m=3*XFeA#}X~BITfLSv| zx#RrjDfjSVtQOVA%B}Ys(zwkI@w_)@u+1)%8F^275qTd$-XY`-d8{_r3SfuKJI;Te zbOXzACksGJr}rDo$;{kr97>{cD^%A;_K6owZ1NGbC#r8(1~b{xSuswEe+HoBi*oDz z+~xwXPg4>zg;H66Gh@F73`_ge`+0r~jl)T3m@}rEQNKnuH3Zvor83hzGs|wp9ZrBA zo{yO^#52S*#IsTHQ$K+^Gt6QnJGG;119&dXU<=>LXV<=7z)Fr>&hkTrY>I0(GuuAJ z25)Dqa1~?!Ez6+y8>XePX^?#y+U+#7+i7UG(@G`}$@XOBWkWw>y#rTL0Lt-Gs58=y zEFE-gbU4?8nY{|SVZbd!i*`ENujggJ?TC4N!-PKHc2^yl+3G}#6- z{8C3p(pdH;jBx;`WIpkJ=xh|t)Jsh)-H^{juN<={!?P=IebD@_FeE+#~jD^r7HG*pOsk)PEUrO(_3CmTNe`QpnH8BIq~g znON4ubU#Gka%h;RD<)t3LkFTL|!G8iU2w<(ayNfUrJ6VgI{?e=Gticv8 zN1N-ac{mT{V%CltI?5ynK)K>mL@%BkoZmb?vy=!M(uJKuSSP~Fy0lwx zwz3alV?7_AFBSUy_F)lCuE&T+MZ$iQZ-Z&3SlDd zv1DsUqt{Ibo$UOqfp-!1953akHqrBgOXZ@lmoGBgITKb%T$b8{UO!HDhFaJN{I*uw zvA>k|y4r70Lu|LnZtbvFwyMrm4XQKDkMq^K+i=YCBsgNiUWTYL#^16G6VB^kTi5kMqPbQr81@ggpx5Sm*jmh3+GYQ)}Bfy9vmwsGw6 zT6MMRk)pBh%e?An=dB0x@KI^#(h5BCp6g;c$QsmY>ieLt^?6s?srtyl z95LD(D(#J4%6}E}#zHNQU@QAFX@Mq2#Tk=m71rQ8>@7%5)wxWb$6Ogps}+ouKnn{y zuveC6tV#16um3t6JwZsA&J}!$G=Mb#Q77Aws>cXK$TZJT|8!iA+tv3^M*Sg)|tKQcL(&!@qSQZJ(uwNlG{=UDG* zm3A%Twoy&KI?ST6ewo7}xi9+wPq)b732Mcj0FBj!+nUt?8kf}r1E_GhFg~$%2qPo| z)oks5Ac@$tEgIU7BzMeIhkP)YF2qYahW15z(jmrhl#-vLq1qB*-;$}L2CFq6_LwHM ziuT0XV|7|bD;q7k{-7e*Xj@dq*fw1lnU_{xcPuUPT^Me`Mn_OXnp!vZPE+G!5nd|V zgT2hHt`Q{*$4UZq$mYndAqzn_WpALvKNwKOai`kVtZSbvL8S*rir8H-x(2tiwUUlg z1k{E6EY%vFgkV6Jo~z7$+W zx9$qBYbmwP2ecfjR1b;F*ynV-Wi_xlLfgFJMe}+^N{(vgWe@4gXA9t5d!9^Fhb~;C znN7CAdk-r=;qkKMu|%-IPs)l`EZT=i^D=LZ#8B&lu8>qqJA#l`P?Zs9vN{yqja73O z`xWU@>m_(cLvNW|h#M!Y_4!tX{kVacbi-{P77I(HrS7^|S$K!hr_)I6y{c(2iFih> zi#J>=y_5a?NLK09MK0=dP8%CS9vCGKRH=OJ6g|(|6ea}GUVYWx5G~f7rI=;zKq&0+ zGeR96zMi`j81NAYt?;lVFdP^m_A#tm4cdd%|Q>16Ur# zyIu=ok0jRwrN?vqKd@6hI{xn{BAVc|a^a3gTLKa{vdcNc};!E}86@P7JP9mr|!>LEpk2 zg0xj?b9m)SHK0kkxVoXPy0)}L=-iC+AC>kX4%5LVoOYo+XsZC>!H~-yB8zc*TYPpG zdgp+z!;UkFXfK~(ZE9N(uWz=jvZ1lgRNf#bd`8%lJ+iZ`LQi2zS3s4+G}%Cd$7&LA;iK zzl{H|`5${<GNiulp;Y5HZK96P;MKEI3~o&G{9 z?zF|Pk879tXz4V2(fo<fOlk4wnWkI&|d(b@1t>LXD>hGl!w;s;k=T)rCp#o|s`fB8mHkC>T`d$h7{kaSy; z1>N{KDtHWnvQN@QB)_}_bWGCqn*_h?1a$4vel3#Ur3vVoB;BComxykKq??r@@|~7| z-ziDgDfvxIK-VP8(JSRkL}$4GotR0+EP|vfmib~SJN}V+9+dJWqSN?ok^Gt@zl?Zp zv3isI@}yp{Wgz~M`JR<@O!7OYKazA2NmnlIB~dxrrF;XDE|Gi#lHZ+D&saH$e`LPB zl5X||=vHX?%5u=&pSVZz>zDk@k}f@t2p&myK++A$a!ejYr?sPFk}glmhgH(}NAeq% zbQYO!BD!8#4vVa}(s*uS;D9iTuJWXOrzF2b_SY);wMx3t^``MFm;5?qc@y>HJ(8bU@=Me{ zvL(O11ofunJ0$sSk>yQf&!g3FA-~qHM$=jT#l{o<3h}-gUCzJM-_!Ir8c)c2*5pc5 zKb`+-_45(OdqZ-3uj#G#Z#3T1_bpB#u)~Vcfvgz zZoH`?VQ-g6dJJmj1Bf2;0Bje4=<&^u{Y1j80AE{% z{nJDPtnGCqyd3)%=OdhO0N{dKzmJjjH$GI3Ejb7${5arYxCel>eT#%wS7CgPaKaA& zhTzukNu<4s%Pf!w;eVHsh$k0gHV)y0-vrzOw|;*i?K>Q2#l33?Cwv*; z0l15SKWh_Z)bAyvJ%-=Je!+gw5dHz+6x{lKgS4M8>t?LKAe`_OfNbom)9(wU{eqV? z!LATacs;-dcMtGm&Cna%`n`d)XK;fHaw44Y7XY0^54;Dn-(u2siImUYz|R4wyo126+=qSu;X}a98$`H%Kc0TCo_-%6?eDu4umNca2LKPlO?VAp zAKZl31D=Gt2RL;T$^y53pC0Ysd%hd>f^fq5_oKhUo;t#roAFzhaAyP0#9q5ua2EqV z3?TXS`}6es?`U7%tRC1N=n2~Zop2Kl0D9o=1b!Q^18(*uthfC;WQJS6kB;`J``l+?~LW0IVbr@GyYd3*nR@#3&zEk(H%hk+_`3jl?+|`nh7&$3-GnQ!UytOh0)Ae)2Z39E zjWR$s!uJD+hVb{K`xx+~)8G%99AGN}Xb9sTb?)u~o__{?6liGA@ecr0#wUSshdR3- z;kav^l>j>7#(nF2FXRTeX-_2WaiqP&glT^xxe3!AMRF6SeTEsJCmaFT;Qs4827VqW z52D5M!+u5t6ps;}YDC|LI69w!rf|+P|N8bek9Ll6LE+q@;zE8rjqV~^P>A*YIc0@( z#?9+;c(4?-ps+&?7GD3E%(VHqeo<{}#(kn-;0-P)#C?v}2Kn*4;G8zMGvEvQT0*#5 zpzT^mu&rqI+(KN`=XJMWJxuNw5xEhoD>Yv5oFn1?=K;g$gP?-5+u08Dj_e(IJ7(=@ z-_f~)CUSBR?%&?Ny>t79?LFJK?4S+wmmqAzzTSO(`-=Bl_FMO_*x$6jbw2{jVLLEG zOYe$ae{XwlPw$rA{@w$j*gClN)YjpxXSZf= z%iCt%wq;xYwgcPFZp+@jWqa@TW82M;!w)&O?C9Mwu;bW{$d2J1**o)gmhCLx*|f8D z=Z2jfF`4t8dq_U4y%Zcb(mpw_Dj=zT2|9 zb+>n literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/url_parser.c b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/url_parser.c new file mode 100644 index 00000000..de5d5b4c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/url_parser.c @@ -0,0 +1,6031 @@ +/* Generated by Cython 0.29.28 */ + +/* BEGIN: Cython Metadata +{ + "distutils": { + "depends": [], + "extra_compile_args": [ + "-O2" + ], + "name": "httptools.parser.url_parser", + "sources": [ + "httptools/parser/url_parser.pyx" + ] + }, + "module_name": "httptools.parser.url_parser" +} +END: Cython Metadata */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_28" +#define CYTHON_HEX_VERSION 0x001D1CF0 +#define CYTHON_FUTURE_DIVISION 1 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030B00A1) + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif +#endif + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #endif +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#ifndef PyObject_Unicode + #define PyObject_Unicode PyObject_Str +#endif +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(WIN32) || defined(MS_WINDOWS) + #define _USE_MATH_DEFINES +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#define __PYX_MARK_ERR_POS(f_index, lineno) \ + { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__httptools__parser__url_parser +#define __PYX_HAVE_API__httptools__parser__url_parser +/* Early includes */ +#include +#include +#include "pythread.h" +#include +#include "http_parser.h" +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + + +static const char *__pyx_f[] = { + "stringsource", + "httptools\\parser\\url_parser.pyx", + "type.pxd", + "bool.pxd", + "complex.pxd", +}; + +/*--- Type declarations ---*/ +struct __pyx_obj_9httptools_6parser_10url_parser_URL; + +/* "httptools/parser/url_parser.pyx":16 + * + * @cython.freelist(250) + * cdef class URL: # <<<<<<<<<<<<<< + * cdef readonly bytes schema + * cdef readonly bytes host + */ +struct __pyx_obj_9httptools_6parser_10url_parser_URL { + PyObject_HEAD + PyObject *schema; + PyObject *host; + PyObject *port; + PyObject *path; + PyObject *query; + PyObject *fragment; + PyObject *userinfo; +}; + + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* ArgTypeTest.proto */ +#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ + ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\ + __Pyx__ArgTypeTest(obj, type, name, exact)) +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif +#if CYTHON_FAST_PYCALL + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* RaiseException.proto */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* PyObjectCall2Args.proto */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* GetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* SwapException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSwap(type, value, tb) __Pyx__ExceptionSwap(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* GetTopmostException.proto */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* SaveResetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +#else +#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) +#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) +#endif + +/* IncludeStringH.proto */ +#include + +/* PyObject_GenericGetAttrNoDict.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr +#endif + +/* PyObject_GenericGetAttr.proto */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr +#endif + +/* PyErrExceptionMatches.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* PyObjectGetAttrStrNoError.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); + +/* SetupReduce.proto */ +static int __Pyx_setup_reduce(PyObject* type_obj); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto +#define __PYX_HAVE_RT_ImportType_proto +enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 +}; +static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); +#endif + +/* Import.proto */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); + +/* ImportFrom.proto */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint16_t(uint16_t value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + +/* Module declarations from 'cpython.mem' */ + +/* Module declarations from 'cpython.version' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.type' */ +static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; + +/* Module declarations from 'libc.string' */ + +/* Module declarations from 'libc.stdio' */ + +/* Module declarations from 'cpython.object' */ + +/* Module declarations from 'cpython.ref' */ + +/* Module declarations from 'cpython.exc' */ + +/* Module declarations from 'cpython.module' */ + +/* Module declarations from 'cpython.tuple' */ + +/* Module declarations from 'cpython.list' */ + +/* Module declarations from 'cpython.sequence' */ + +/* Module declarations from 'cpython.mapping' */ + +/* Module declarations from 'cpython.iterator' */ + +/* Module declarations from 'cpython.number' */ + +/* Module declarations from 'cpython.int' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.bool' */ +static PyTypeObject *__pyx_ptype_7cpython_4bool_bool = 0; + +/* Module declarations from 'cpython.long' */ + +/* Module declarations from 'cpython.float' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.complex' */ +static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0; + +/* Module declarations from 'cpython.string' */ + +/* Module declarations from 'cpython.unicode' */ + +/* Module declarations from 'cpython.dict' */ + +/* Module declarations from 'cpython.instance' */ + +/* Module declarations from 'cpython.function' */ + +/* Module declarations from 'cpython.method' */ + +/* Module declarations from 'cpython.weakref' */ + +/* Module declarations from 'cpython.getargs' */ + +/* Module declarations from 'cpython.pythread' */ + +/* Module declarations from 'cpython.pystate' */ + +/* Module declarations from 'cpython.cobject' */ + +/* Module declarations from 'cpython.oldbuffer' */ + +/* Module declarations from 'cpython.set' */ + +/* Module declarations from 'cpython.buffer' */ + +/* Module declarations from 'cpython.bytes' */ + +/* Module declarations from 'cpython.pycapsule' */ + +/* Module declarations from 'cpython' */ + +/* Module declarations from 'cython' */ + +/* Module declarations from 'httptools.parser' */ + +/* Module declarations from 'libc.stdint' */ + +/* Module declarations from 'httptools.parser.url_cparser' */ + +/* Module declarations from 'httptools.parser.url_parser' */ +static PyTypeObject *__pyx_ptype_9httptools_6parser_10url_parser_URL = 0; +#define __Pyx_MODULE_NAME "httptools.parser.url_parser" +extern int __pyx_module_is_main_httptools__parser__url_parser; +int __pyx_module_is_main_httptools__parser__url_parser = 0; + +/* Implementation of 'httptools.parser.url_parser' */ +static PyObject *__pyx_builtin_TypeError; +static const char __pyx_k_ln[] = "ln"; +static const char __pyx_k_URL[] = "URL"; +static const char __pyx_k_all[] = "__all__"; +static const char __pyx_k_off[] = "off"; +static const char __pyx_k_res[] = "res"; +static const char __pyx_k_url[] = "url"; +static const char __pyx_k_host[] = "host"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_path[] = "path"; +static const char __pyx_k_port[] = "port"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_query[] = "query"; +static const char __pyx_k_errors[] = "errors"; +static const char __pyx_k_format[] = "format"; +static const char __pyx_k_import[] = "__import__"; +static const char __pyx_k_parsed[] = "parsed"; +static const char __pyx_k_py_buf[] = "py_buf"; +static const char __pyx_k_reduce[] = "__reduce__"; +static const char __pyx_k_result[] = "result"; +static const char __pyx_k_schema[] = "schema"; +static const char __pyx_k_buf_data[] = "buf_data"; +static const char __pyx_k_fragment[] = "fragment"; +static const char __pyx_k_getstate[] = "__getstate__"; +static const char __pyx_k_setstate[] = "__setstate__"; +static const char __pyx_k_userinfo[] = "userinfo"; +static const char __pyx_k_TypeError[] = "TypeError"; +static const char __pyx_k_parse_url[] = "parse_url"; +static const char __pyx_k_reduce_ex[] = "__reduce_ex__"; +static const char __pyx_k_invalid_url_r[] = "invalid url {!r}"; +static const char __pyx_k_reduce_cython[] = "__reduce_cython__"; +static const char __pyx_k_setstate_cython[] = "__setstate_cython__"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_HttpParserInvalidURLError[] = "HttpParserInvalidURLError"; +static const char __pyx_k_httptools_parser_url_parser[] = "httptools.parser.url_parser"; +static const char __pyx_k_URL_schema_r_host_r_port_r_path[] = ""; +static const char __pyx_k_httptools_parser_url_parser_pyx[] = "httptools\\parser\\url_parser.pyx"; +static const char __pyx_k_no_default___reduce___due_to_non[] = "no default __reduce__ due to non-trivial __cinit__"; +static PyObject *__pyx_n_s_HttpParserInvalidURLError; +static PyObject *__pyx_n_s_TypeError; +static PyObject *__pyx_n_s_URL; +static PyObject *__pyx_kp_u_URL_schema_r_host_r_port_r_path; +static PyObject *__pyx_n_s_all; +static PyObject *__pyx_n_s_buf_data; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_errors; +static PyObject *__pyx_n_s_format; +static PyObject *__pyx_n_s_fragment; +static PyObject *__pyx_n_s_getstate; +static PyObject *__pyx_n_s_host; +static PyObject *__pyx_n_s_httptools_parser_url_parser; +static PyObject *__pyx_kp_s_httptools_parser_url_parser_pyx; +static PyObject *__pyx_n_s_import; +static PyObject *__pyx_kp_u_invalid_url_r; +static PyObject *__pyx_n_s_ln; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_kp_s_no_default___reduce___due_to_non; +static PyObject *__pyx_n_s_off; +static PyObject *__pyx_n_s_parse_url; +static PyObject *__pyx_n_u_parse_url; +static PyObject *__pyx_n_s_parsed; +static PyObject *__pyx_n_s_path; +static PyObject *__pyx_n_s_port; +static PyObject *__pyx_n_s_py_buf; +static PyObject *__pyx_n_s_query; +static PyObject *__pyx_n_s_reduce; +static PyObject *__pyx_n_s_reduce_cython; +static PyObject *__pyx_n_s_reduce_ex; +static PyObject *__pyx_n_s_res; +static PyObject *__pyx_n_s_result; +static PyObject *__pyx_n_s_schema; +static PyObject *__pyx_n_s_setstate; +static PyObject *__pyx_n_s_setstate_cython; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_n_s_url; +static PyObject *__pyx_n_s_userinfo; +static int __pyx_pf_9httptools_6parser_10url_parser_3URL___cinit__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self, PyObject *__pyx_v_schema, PyObject *__pyx_v_host, PyObject *__pyx_v_port, PyObject *__pyx_v_path, PyObject *__pyx_v_query, PyObject *__pyx_v_fragment, PyObject *__pyx_v_userinfo); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_2__repr__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_6schema___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4host___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4port___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4path___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_5query___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_8fragment___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_8userinfo___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_6__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_parse_url(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_url); /* proto */ +static PyObject *__pyx_tp_new_9httptools_6parser_10url_parser_URL(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ +static PyObject *__pyx_tuple_; +static PyObject *__pyx_tuple__2; +static PyObject *__pyx_tuple__3; +static PyObject *__pyx_tuple__4; +static PyObject *__pyx_codeobj__5; +/* Late includes */ + +/* "httptools/parser/url_parser.pyx":25 + * cdef readonly bytes userinfo + * + * def __cinit__(self, bytes schema, bytes host, object port, bytes path, # <<<<<<<<<<<<<< + * bytes query, bytes fragment, bytes userinfo): + * + */ + +/* Python wrapper */ +static int __pyx_pw_9httptools_6parser_10url_parser_3URL_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static int __pyx_pw_9httptools_6parser_10url_parser_3URL_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_schema = 0; + PyObject *__pyx_v_host = 0; + PyObject *__pyx_v_port = 0; + PyObject *__pyx_v_path = 0; + PyObject *__pyx_v_query = 0; + PyObject *__pyx_v_fragment = 0; + PyObject *__pyx_v_userinfo = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_schema,&__pyx_n_s_host,&__pyx_n_s_port,&__pyx_n_s_path,&__pyx_n_s_query,&__pyx_n_s_fragment,&__pyx_n_s_userinfo,0}; + PyObject* values[7] = {0,0,0,0,0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6); + CYTHON_FALLTHROUGH; + case 6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5); + CYTHON_FALLTHROUGH; + case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + CYTHON_FALLTHROUGH; + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + CYTHON_FALLTHROUGH; + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_schema)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_host)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 7, 7, 1); __PYX_ERR(1, 25, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_port)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 7, 7, 2); __PYX_ERR(1, 25, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 3: + if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_path)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 7, 7, 3); __PYX_ERR(1, 25, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 4: + if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_query)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 7, 7, 4); __PYX_ERR(1, 25, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 5: + if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_fragment)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 7, 7, 5); __PYX_ERR(1, 25, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 6: + if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_userinfo)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 7, 7, 6); __PYX_ERR(1, 25, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) __PYX_ERR(1, 25, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 7) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + values[5] = PyTuple_GET_ITEM(__pyx_args, 5); + values[6] = PyTuple_GET_ITEM(__pyx_args, 6); + } + __pyx_v_schema = ((PyObject*)values[0]); + __pyx_v_host = ((PyObject*)values[1]); + __pyx_v_port = values[2]; + __pyx_v_path = ((PyObject*)values[3]); + __pyx_v_query = ((PyObject*)values[4]); + __pyx_v_fragment = ((PyObject*)values[5]); + __pyx_v_userinfo = ((PyObject*)values[6]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 7, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(1, 25, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("httptools.parser.url_parser.URL.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return -1; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_schema), (&PyBytes_Type), 1, "schema", 1))) __PYX_ERR(1, 25, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_host), (&PyBytes_Type), 1, "host", 1))) __PYX_ERR(1, 25, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_path), (&PyBytes_Type), 1, "path", 1))) __PYX_ERR(1, 25, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_query), (&PyBytes_Type), 1, "query", 1))) __PYX_ERR(1, 26, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_fragment), (&PyBytes_Type), 1, "fragment", 1))) __PYX_ERR(1, 26, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_userinfo), (&PyBytes_Type), 1, "userinfo", 1))) __PYX_ERR(1, 26, __pyx_L1_error) + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL___cinit__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self), __pyx_v_schema, __pyx_v_host, __pyx_v_port, __pyx_v_path, __pyx_v_query, __pyx_v_fragment, __pyx_v_userinfo); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_9httptools_6parser_10url_parser_3URL___cinit__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self, PyObject *__pyx_v_schema, PyObject *__pyx_v_host, PyObject *__pyx_v_port, PyObject *__pyx_v_path, PyObject *__pyx_v_query, PyObject *__pyx_v_fragment, PyObject *__pyx_v_userinfo) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__cinit__", 0); + + /* "httptools/parser/url_parser.pyx":28 + * bytes query, bytes fragment, bytes userinfo): + * + * self.schema = schema # <<<<<<<<<<<<<< + * self.host = host + * self.port = port + */ + __Pyx_INCREF(__pyx_v_schema); + __Pyx_GIVEREF(__pyx_v_schema); + __Pyx_GOTREF(__pyx_v_self->schema); + __Pyx_DECREF(__pyx_v_self->schema); + __pyx_v_self->schema = __pyx_v_schema; + + /* "httptools/parser/url_parser.pyx":29 + * + * self.schema = schema + * self.host = host # <<<<<<<<<<<<<< + * self.port = port + * self.path = path + */ + __Pyx_INCREF(__pyx_v_host); + __Pyx_GIVEREF(__pyx_v_host); + __Pyx_GOTREF(__pyx_v_self->host); + __Pyx_DECREF(__pyx_v_self->host); + __pyx_v_self->host = __pyx_v_host; + + /* "httptools/parser/url_parser.pyx":30 + * self.schema = schema + * self.host = host + * self.port = port # <<<<<<<<<<<<<< + * self.path = path + * self.query = query + */ + __Pyx_INCREF(__pyx_v_port); + __Pyx_GIVEREF(__pyx_v_port); + __Pyx_GOTREF(__pyx_v_self->port); + __Pyx_DECREF(__pyx_v_self->port); + __pyx_v_self->port = __pyx_v_port; + + /* "httptools/parser/url_parser.pyx":31 + * self.host = host + * self.port = port + * self.path = path # <<<<<<<<<<<<<< + * self.query = query + * self.fragment = fragment + */ + __Pyx_INCREF(__pyx_v_path); + __Pyx_GIVEREF(__pyx_v_path); + __Pyx_GOTREF(__pyx_v_self->path); + __Pyx_DECREF(__pyx_v_self->path); + __pyx_v_self->path = __pyx_v_path; + + /* "httptools/parser/url_parser.pyx":32 + * self.port = port + * self.path = path + * self.query = query # <<<<<<<<<<<<<< + * self.fragment = fragment + * self.userinfo = userinfo + */ + __Pyx_INCREF(__pyx_v_query); + __Pyx_GIVEREF(__pyx_v_query); + __Pyx_GOTREF(__pyx_v_self->query); + __Pyx_DECREF(__pyx_v_self->query); + __pyx_v_self->query = __pyx_v_query; + + /* "httptools/parser/url_parser.pyx":33 + * self.path = path + * self.query = query + * self.fragment = fragment # <<<<<<<<<<<<<< + * self.userinfo = userinfo + * + */ + __Pyx_INCREF(__pyx_v_fragment); + __Pyx_GIVEREF(__pyx_v_fragment); + __Pyx_GOTREF(__pyx_v_self->fragment); + __Pyx_DECREF(__pyx_v_self->fragment); + __pyx_v_self->fragment = __pyx_v_fragment; + + /* "httptools/parser/url_parser.pyx":34 + * self.query = query + * self.fragment = fragment + * self.userinfo = userinfo # <<<<<<<<<<<<<< + * + * def __repr__(self): + */ + __Pyx_INCREF(__pyx_v_userinfo); + __Pyx_GIVEREF(__pyx_v_userinfo); + __Pyx_GOTREF(__pyx_v_self->userinfo); + __Pyx_DECREF(__pyx_v_self->userinfo); + __pyx_v_self->userinfo = __pyx_v_userinfo; + + /* "httptools/parser/url_parser.pyx":25 + * cdef readonly bytes userinfo + * + * def __cinit__(self, bytes schema, bytes host, object port, bytes path, # <<<<<<<<<<<<<< + * bytes query, bytes fragment, bytes userinfo): + * + */ + + /* function exit code */ + __pyx_r = 0; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":36 + * self.userinfo = userinfo + * + * def __repr__(self): # <<<<<<<<<<<<<< + * return ('' + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_3__repr__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_3__repr__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_2__repr__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_2__repr__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__repr__", 0); + + /* "httptools/parser/url_parser.pyx":37 + * + * def __repr__(self): + * return ('' + * .format(self.schema, self.host, self.port, self.path, + */ + __Pyx_XDECREF(__pyx_r); + + /* "httptools/parser/url_parser.pyx":39 + * return ('' + * .format(self.schema, self.host, self.port, self.path, # <<<<<<<<<<<<<< + * self.query, self.fragment, self.userinfo)) + * + */ + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_URL_schema_r_host_r_port_r_path, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 39, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + + /* "httptools/parser/url_parser.pyx":40 + * 'query: {!r}, fragment: {!r}, userinfo: {!r}>' + * .format(self.schema, self.host, self.port, self.path, + * self.query, self.fragment, self.userinfo)) # <<<<<<<<<<<<<< + * + * + */ + __pyx_t_3 = NULL; + __pyx_t_4 = 0; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + __pyx_t_4 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_2)) { + PyObject *__pyx_temp[8] = {__pyx_t_3, __pyx_v_self->schema, __pyx_v_self->host, __pyx_v_self->port, __pyx_v_self->path, __pyx_v_self->query, __pyx_v_self->fragment, __pyx_v_self->userinfo}; + __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_4, 7+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 39, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) { + PyObject *__pyx_temp[8] = {__pyx_t_3, __pyx_v_self->schema, __pyx_v_self->host, __pyx_v_self->port, __pyx_v_self->path, __pyx_v_self->query, __pyx_v_self->fragment, __pyx_v_self->userinfo}; + __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_4, 7+__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 39, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GOTREF(__pyx_t_1); + } else + #endif + { + __pyx_t_5 = PyTuple_New(7+__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 39, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (__pyx_t_3) { + __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __pyx_t_3 = NULL; + } + __Pyx_INCREF(__pyx_v_self->schema); + __Pyx_GIVEREF(__pyx_v_self->schema); + PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_4, __pyx_v_self->schema); + __Pyx_INCREF(__pyx_v_self->host); + __Pyx_GIVEREF(__pyx_v_self->host); + PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_4, __pyx_v_self->host); + __Pyx_INCREF(__pyx_v_self->port); + __Pyx_GIVEREF(__pyx_v_self->port); + PyTuple_SET_ITEM(__pyx_t_5, 2+__pyx_t_4, __pyx_v_self->port); + __Pyx_INCREF(__pyx_v_self->path); + __Pyx_GIVEREF(__pyx_v_self->path); + PyTuple_SET_ITEM(__pyx_t_5, 3+__pyx_t_4, __pyx_v_self->path); + __Pyx_INCREF(__pyx_v_self->query); + __Pyx_GIVEREF(__pyx_v_self->query); + PyTuple_SET_ITEM(__pyx_t_5, 4+__pyx_t_4, __pyx_v_self->query); + __Pyx_INCREF(__pyx_v_self->fragment); + __Pyx_GIVEREF(__pyx_v_self->fragment); + PyTuple_SET_ITEM(__pyx_t_5, 5+__pyx_t_4, __pyx_v_self->fragment); + __Pyx_INCREF(__pyx_v_self->userinfo); + __Pyx_GIVEREF(__pyx_v_self->userinfo); + PyTuple_SET_ITEM(__pyx_t_5, 6+__pyx_t_4, __pyx_v_self->userinfo); + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 39, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "httptools/parser/url_parser.pyx":36 + * self.userinfo = userinfo + * + * def __repr__(self): # <<<<<<<<<<<<<< + * return ('' + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_AddTraceback("httptools.parser.url_parser.URL.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":17 + * @cython.freelist(250) + * cdef class URL: + * cdef readonly bytes schema # <<<<<<<<<<<<<< + * cdef readonly bytes host + * cdef readonly object port + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_6schema_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_6schema_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_6schema___get__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_6schema___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->schema); + __pyx_r = __pyx_v_self->schema; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":18 + * cdef class URL: + * cdef readonly bytes schema + * cdef readonly bytes host # <<<<<<<<<<<<<< + * cdef readonly object port + * cdef readonly bytes path + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_4host_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_4host_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_4host___get__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4host___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->host); + __pyx_r = __pyx_v_self->host; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":19 + * cdef readonly bytes schema + * cdef readonly bytes host + * cdef readonly object port # <<<<<<<<<<<<<< + * cdef readonly bytes path + * cdef readonly bytes query + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_4port_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_4port_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_4port___get__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4port___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->port); + __pyx_r = __pyx_v_self->port; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":20 + * cdef readonly bytes host + * cdef readonly object port + * cdef readonly bytes path # <<<<<<<<<<<<<< + * cdef readonly bytes query + * cdef readonly bytes fragment + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_4path_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_4path_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_4path___get__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4path___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->path); + __pyx_r = __pyx_v_self->path; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":21 + * cdef readonly object port + * cdef readonly bytes path + * cdef readonly bytes query # <<<<<<<<<<<<<< + * cdef readonly bytes fragment + * cdef readonly bytes userinfo + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_5query_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_5query_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_5query___get__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_5query___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->query); + __pyx_r = __pyx_v_self->query; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":22 + * cdef readonly bytes path + * cdef readonly bytes query + * cdef readonly bytes fragment # <<<<<<<<<<<<<< + * cdef readonly bytes userinfo + * + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_8fragment_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_8fragment_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_8fragment___get__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_8fragment___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->fragment); + __pyx_r = __pyx_v_self->fragment; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":23 + * cdef readonly bytes query + * cdef readonly bytes fragment + * cdef readonly bytes userinfo # <<<<<<<<<<<<<< + * + * def __cinit__(self, bytes schema, bytes host, object port, bytes path, + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_8userinfo_1__get__(PyObject *__pyx_v_self); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_8userinfo_1__get__(PyObject *__pyx_v_self) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_8userinfo___get__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_8userinfo___get__(struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__get__", 0); + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_self->userinfo); + __pyx_r = __pyx_v_self->userinfo; + goto __pyx_L0; + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_4__reduce_cython__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__reduce_cython__", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(0, 2, __pyx_L1_error) + + /* "(tree fragment)":1 + * def __reduce_cython__(self): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.url_parser.URL.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_3URL_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_3URL_6__setstate_cython__(((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_3URL_6__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__setstate_cython__", 0); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_Raise(__pyx_t_1, 0, 0, 0); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __PYX_ERR(0, 4, __pyx_L1_error) + + /* "(tree fragment)":3 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("httptools.parser.url_parser.URL.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "httptools/parser/url_parser.pyx":43 + * + * + * def parse_url(url): # <<<<<<<<<<<<<< + * cdef: + * Py_buffer py_buf + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_1parse_url(PyObject *__pyx_self, PyObject *__pyx_v_url); /*proto*/ +static PyMethodDef __pyx_mdef_9httptools_6parser_10url_parser_1parse_url = {"parse_url", (PyCFunction)__pyx_pw_9httptools_6parser_10url_parser_1parse_url, METH_O, 0}; +static PyObject *__pyx_pw_9httptools_6parser_10url_parser_1parse_url(PyObject *__pyx_self, PyObject *__pyx_v_url) { + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("parse_url (wrapper)", 0); + __pyx_r = __pyx_pf_9httptools_6parser_10url_parser_parse_url(__pyx_self, ((PyObject *)__pyx_v_url)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_9httptools_6parser_10url_parser_parse_url(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_url) { + Py_buffer __pyx_v_py_buf; + char *__pyx_v_buf_data; + struct http_parser_url *__pyx_v_parsed; + int __pyx_v_res; + PyObject *__pyx_v_schema = 0; + PyObject *__pyx_v_host = 0; + PyObject *__pyx_v_port = 0; + PyObject *__pyx_v_path = 0; + PyObject *__pyx_v_query = 0; + PyObject *__pyx_v_fragment = 0; + PyObject *__pyx_v_userinfo = 0; + CYTHON_UNUSED PyObject *__pyx_v_result = 0; + int __pyx_v_off; + int __pyx_v_ln; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + uint16_t __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_t_9; + char const *__pyx_t_10; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("parse_url", 0); + + /* "httptools/parser/url_parser.pyx":49 + * uparser.http_parser_url* parsed + * int res + * bytes schema = None # <<<<<<<<<<<<<< + * bytes host = None + * object port = None + */ + __Pyx_INCREF(Py_None); + __pyx_v_schema = ((PyObject*)Py_None); + + /* "httptools/parser/url_parser.pyx":50 + * int res + * bytes schema = None + * bytes host = None # <<<<<<<<<<<<<< + * object port = None + * bytes path = None + */ + __Pyx_INCREF(Py_None); + __pyx_v_host = ((PyObject*)Py_None); + + /* "httptools/parser/url_parser.pyx":51 + * bytes schema = None + * bytes host = None + * object port = None # <<<<<<<<<<<<<< + * bytes path = None + * bytes query = None + */ + __Pyx_INCREF(Py_None); + __pyx_v_port = Py_None; + + /* "httptools/parser/url_parser.pyx":52 + * bytes host = None + * object port = None + * bytes path = None # <<<<<<<<<<<<<< + * bytes query = None + * bytes fragment = None + */ + __Pyx_INCREF(Py_None); + __pyx_v_path = ((PyObject*)Py_None); + + /* "httptools/parser/url_parser.pyx":53 + * object port = None + * bytes path = None + * bytes query = None # <<<<<<<<<<<<<< + * bytes fragment = None + * bytes userinfo = None + */ + __Pyx_INCREF(Py_None); + __pyx_v_query = ((PyObject*)Py_None); + + /* "httptools/parser/url_parser.pyx":54 + * bytes path = None + * bytes query = None + * bytes fragment = None # <<<<<<<<<<<<<< + * bytes userinfo = None + * object result = None + */ + __Pyx_INCREF(Py_None); + __pyx_v_fragment = ((PyObject*)Py_None); + + /* "httptools/parser/url_parser.pyx":55 + * bytes query = None + * bytes fragment = None + * bytes userinfo = None # <<<<<<<<<<<<<< + * object result = None + * int off + */ + __Pyx_INCREF(Py_None); + __pyx_v_userinfo = ((PyObject*)Py_None); + + /* "httptools/parser/url_parser.pyx":56 + * bytes fragment = None + * bytes userinfo = None + * object result = None # <<<<<<<<<<<<<< + * int off + * int ln + */ + __Pyx_INCREF(Py_None); + __pyx_v_result = Py_None; + + /* "httptools/parser/url_parser.pyx":60 + * int ln + * + * parsed = \ # <<<<<<<<<<<<<< + * PyMem_Malloc(sizeof(uparser.http_parser_url)) + * uparser.http_parser_url_init(parsed) + */ + __pyx_v_parsed = ((struct http_parser_url *)PyMem_Malloc((sizeof(struct http_parser_url)))); + + /* "httptools/parser/url_parser.pyx":62 + * parsed = \ + * PyMem_Malloc(sizeof(uparser.http_parser_url)) + * uparser.http_parser_url_init(parsed) # <<<<<<<<<<<<<< + * + * PyObject_GetBuffer(url, &py_buf, PyBUF_SIMPLE) + */ + http_parser_url_init(__pyx_v_parsed); + + /* "httptools/parser/url_parser.pyx":64 + * uparser.http_parser_url_init(parsed) + * + * PyObject_GetBuffer(url, &py_buf, PyBUF_SIMPLE) # <<<<<<<<<<<<<< + * try: + * buf_data = py_buf.buf + */ + __pyx_t_1 = PyObject_GetBuffer(__pyx_v_url, (&__pyx_v_py_buf), PyBUF_SIMPLE); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(1, 64, __pyx_L1_error) + + /* "httptools/parser/url_parser.pyx":65 + * + * 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) + */ + /*try:*/ { + + /* "httptools/parser/url_parser.pyx":66 + * 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) + * + */ + __pyx_v_buf_data = ((char *)__pyx_v_py_buf.buf); + + /* "httptools/parser/url_parser.pyx":67 + * try: + * buf_data = py_buf.buf + * res = uparser.http_parser_parse_url(buf_data, py_buf.len, 0, parsed) # <<<<<<<<<<<<<< + * + * if res == 0: + */ + __pyx_v_res = http_parser_parse_url(__pyx_v_buf_data, __pyx_v_py_buf.len, 0, __pyx_v_parsed); + + /* "httptools/parser/url_parser.pyx":69 + * 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 + */ + __pyx_t_2 = ((__pyx_v_res == 0) != 0); + if (likely(__pyx_t_2)) { + + /* "httptools/parser/url_parser.pyx":70 + * + * 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 + */ + __pyx_t_2 = ((__pyx_v_parsed->field_set & (1 << UF_SCHEMA)) != 0); + if (__pyx_t_2) { + + /* "httptools/parser/url_parser.pyx":71 + * 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] + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_SCHEMA)]).off; + __pyx_v_off = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":72 + * 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] + * + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_SCHEMA)]).len; + __pyx_v_ln = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":73 + * 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): + */ + __pyx_t_4 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_buf_data + __pyx_v_off, (__pyx_v_off + __pyx_v_ln) - __pyx_v_off); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 73, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_schema, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "httptools/parser/url_parser.pyx":70 + * + * 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 + */ + } + + /* "httptools/parser/url_parser.pyx":75 + * 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 + */ + __pyx_t_2 = ((__pyx_v_parsed->field_set & (1 << UF_HOST)) != 0); + if (__pyx_t_2) { + + /* "httptools/parser/url_parser.pyx":76 + * + * 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] + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_HOST)]).off; + __pyx_v_off = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":77 + * 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] + * + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_HOST)]).len; + __pyx_v_ln = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":78 + * 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): + */ + __pyx_t_4 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_buf_data + __pyx_v_off, (__pyx_v_off + __pyx_v_ln) - __pyx_v_off); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 78, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_host, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "httptools/parser/url_parser.pyx":75 + * 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 + */ + } + + /* "httptools/parser/url_parser.pyx":80 + * host = buf_data[off:off+ln] + * + * if parsed.field_set & (1 << uparser.UF_PORT): # <<<<<<<<<<<<<< + * port = parsed.port + * + */ + __pyx_t_2 = ((__pyx_v_parsed->field_set & (1 << UF_PORT)) != 0); + if (__pyx_t_2) { + + /* "httptools/parser/url_parser.pyx":81 + * + * if parsed.field_set & (1 << uparser.UF_PORT): + * port = parsed.port # <<<<<<<<<<<<<< + * + * if parsed.field_set & (1 << uparser.UF_PATH): + */ + __pyx_t_4 = __Pyx_PyInt_From_uint16_t(__pyx_v_parsed->port); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 81, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_port, __pyx_t_4); + __pyx_t_4 = 0; + + /* "httptools/parser/url_parser.pyx":80 + * host = buf_data[off:off+ln] + * + * if parsed.field_set & (1 << uparser.UF_PORT): # <<<<<<<<<<<<<< + * port = parsed.port + * + */ + } + + /* "httptools/parser/url_parser.pyx":83 + * 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 + */ + __pyx_t_2 = ((__pyx_v_parsed->field_set & (1 << UF_PATH)) != 0); + if (__pyx_t_2) { + + /* "httptools/parser/url_parser.pyx":84 + * + * 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] + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_PATH)]).off; + __pyx_v_off = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":85 + * 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] + * + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_PATH)]).len; + __pyx_v_ln = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":86 + * 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): + */ + __pyx_t_4 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_buf_data + __pyx_v_off, (__pyx_v_off + __pyx_v_ln) - __pyx_v_off); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 86, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_path, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "httptools/parser/url_parser.pyx":83 + * 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 + */ + } + + /* "httptools/parser/url_parser.pyx":88 + * 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 + */ + __pyx_t_2 = ((__pyx_v_parsed->field_set & (1 << UF_QUERY)) != 0); + if (__pyx_t_2) { + + /* "httptools/parser/url_parser.pyx":89 + * + * 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] + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_QUERY)]).off; + __pyx_v_off = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":90 + * 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] + * + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_QUERY)]).len; + __pyx_v_ln = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":91 + * 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): + */ + __pyx_t_4 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_buf_data + __pyx_v_off, (__pyx_v_off + __pyx_v_ln) - __pyx_v_off); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 91, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_query, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "httptools/parser/url_parser.pyx":88 + * 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 + */ + } + + /* "httptools/parser/url_parser.pyx":93 + * 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 + */ + __pyx_t_2 = ((__pyx_v_parsed->field_set & (1 << UF_FRAGMENT)) != 0); + if (__pyx_t_2) { + + /* "httptools/parser/url_parser.pyx":94 + * + * 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] + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_FRAGMENT)]).off; + __pyx_v_off = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":95 + * 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] + * + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_FRAGMENT)]).len; + __pyx_v_ln = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":96 + * 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): + */ + __pyx_t_4 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_buf_data + __pyx_v_off, (__pyx_v_off + __pyx_v_ln) - __pyx_v_off); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 96, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_fragment, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "httptools/parser/url_parser.pyx":93 + * 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 + */ + } + + /* "httptools/parser/url_parser.pyx":98 + * 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 + */ + __pyx_t_2 = ((__pyx_v_parsed->field_set & (1 << UF_USERINFO)) != 0); + if (__pyx_t_2) { + + /* "httptools/parser/url_parser.pyx":99 + * + * 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] + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_USERINFO)]).off; + __pyx_v_off = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":100 + * 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] + * + */ + __pyx_t_3 = (__pyx_v_parsed->field_data[((int)UF_USERINFO)]).len; + __pyx_v_ln = __pyx_t_3; + + /* "httptools/parser/url_parser.pyx":101 + * 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) + */ + __pyx_t_4 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_buf_data + __pyx_v_off, (__pyx_v_off + __pyx_v_ln) - __pyx_v_off); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 101, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_userinfo, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "httptools/parser/url_parser.pyx":98 + * 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 + */ + } + + /* "httptools/parser/url_parser.pyx":103 + * userinfo = buf_data[off:off+ln] + * + * return URL(schema, host, port, path, query, fragment, userinfo) # <<<<<<<<<<<<<< + * else: + * raise HttpParserInvalidURLError("invalid url {!r}".format(url)) + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_4 = PyTuple_New(7); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 103, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_schema); + __Pyx_GIVEREF(__pyx_v_schema); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_schema); + __Pyx_INCREF(__pyx_v_host); + __Pyx_GIVEREF(__pyx_v_host); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_host); + __Pyx_INCREF(__pyx_v_port); + __Pyx_GIVEREF(__pyx_v_port); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_port); + __Pyx_INCREF(__pyx_v_path); + __Pyx_GIVEREF(__pyx_v_path); + PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_v_path); + __Pyx_INCREF(__pyx_v_query); + __Pyx_GIVEREF(__pyx_v_query); + PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_v_query); + __Pyx_INCREF(__pyx_v_fragment); + __Pyx_GIVEREF(__pyx_v_fragment); + PyTuple_SET_ITEM(__pyx_t_4, 5, __pyx_v_fragment); + __Pyx_INCREF(__pyx_v_userinfo); + __Pyx_GIVEREF(__pyx_v_userinfo); + PyTuple_SET_ITEM(__pyx_t_4, 6, __pyx_v_userinfo); + __pyx_t_5 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9httptools_6parser_10url_parser_URL), __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 103, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L3_return; + + /* "httptools/parser/url_parser.pyx":69 + * 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 + */ + } + + /* "httptools/parser/url_parser.pyx":105 + * return URL(schema, host, port, path, query, fragment, userinfo) + * else: + * raise HttpParserInvalidURLError("invalid url {!r}".format(url)) # <<<<<<<<<<<<<< + * finally: + * PyBuffer_Release(&py_buf) + */ + /*else*/ { + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_HttpParserInvalidURLError); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 105, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_invalid_url_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 105, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_8)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_url) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_url); + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 105, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 105, __pyx_L4_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_5, 0, 0, 0); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __PYX_ERR(1, 105, __pyx_L4_error) + } + } + + /* "httptools/parser/url_parser.pyx":107 + * raise HttpParserInvalidURLError("invalid url {!r}".format(url)) + * finally: + * PyBuffer_Release(&py_buf) # <<<<<<<<<<<<<< + * PyMem_Free(parsed) + */ + /*finally:*/ { + __pyx_L4_error:; + /*exception exit:*/{ + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; + if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16); + if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_11, &__pyx_t_12, &__pyx_t_13) < 0)) __Pyx_ErrFetch(&__pyx_t_11, &__pyx_t_12, &__pyx_t_13); + __Pyx_XGOTREF(__pyx_t_11); + __Pyx_XGOTREF(__pyx_t_12); + __Pyx_XGOTREF(__pyx_t_13); + __Pyx_XGOTREF(__pyx_t_14); + __Pyx_XGOTREF(__pyx_t_15); + __Pyx_XGOTREF(__pyx_t_16); + __pyx_t_1 = __pyx_lineno; __pyx_t_9 = __pyx_clineno; __pyx_t_10 = __pyx_filename; + { + PyBuffer_Release((&__pyx_v_py_buf)); + + /* "httptools/parser/url_parser.pyx":108 + * finally: + * PyBuffer_Release(&py_buf) + * PyMem_Free(parsed) # <<<<<<<<<<<<<< + */ + PyMem_Free(__pyx_v_parsed); + } + if (PY_MAJOR_VERSION >= 3) { + __Pyx_XGIVEREF(__pyx_t_14); + __Pyx_XGIVEREF(__pyx_t_15); + __Pyx_XGIVEREF(__pyx_t_16); + __Pyx_ExceptionReset(__pyx_t_14, __pyx_t_15, __pyx_t_16); + } + __Pyx_XGIVEREF(__pyx_t_11); + __Pyx_XGIVEREF(__pyx_t_12); + __Pyx_XGIVEREF(__pyx_t_13); + __Pyx_ErrRestore(__pyx_t_11, __pyx_t_12, __pyx_t_13); + __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; + __pyx_lineno = __pyx_t_1; __pyx_clineno = __pyx_t_9; __pyx_filename = __pyx_t_10; + goto __pyx_L1_error; + } + __pyx_L3_return: { + __pyx_t_16 = __pyx_r; + __pyx_r = 0; + + /* "httptools/parser/url_parser.pyx":107 + * raise HttpParserInvalidURLError("invalid url {!r}".format(url)) + * finally: + * PyBuffer_Release(&py_buf) # <<<<<<<<<<<<<< + * PyMem_Free(parsed) + */ + PyBuffer_Release((&__pyx_v_py_buf)); + + /* "httptools/parser/url_parser.pyx":108 + * finally: + * PyBuffer_Release(&py_buf) + * PyMem_Free(parsed) # <<<<<<<<<<<<<< + */ + PyMem_Free(__pyx_v_parsed); + __pyx_r = __pyx_t_16; + __pyx_t_16 = 0; + goto __pyx_L0; + } + } + + /* "httptools/parser/url_parser.pyx":43 + * + * + * def parse_url(url): # <<<<<<<<<<<<<< + * cdef: + * Py_buffer py_buf + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("httptools.parser.url_parser.parse_url", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_schema); + __Pyx_XDECREF(__pyx_v_host); + __Pyx_XDECREF(__pyx_v_port); + __Pyx_XDECREF(__pyx_v_path); + __Pyx_XDECREF(__pyx_v_query); + __Pyx_XDECREF(__pyx_v_fragment); + __Pyx_XDECREF(__pyx_v_userinfo); + __Pyx_XDECREF(__pyx_v_result); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static struct __pyx_obj_9httptools_6parser_10url_parser_URL *__pyx_freelist_9httptools_6parser_10url_parser_URL[250]; +static int __pyx_freecount_9httptools_6parser_10url_parser_URL = 0; + +static PyObject *__pyx_tp_new_9httptools_6parser_10url_parser_URL(PyTypeObject *t, PyObject *a, PyObject *k) { + struct __pyx_obj_9httptools_6parser_10url_parser_URL *p; + PyObject *o; + if (CYTHON_COMPILING_IN_CPYTHON && likely((__pyx_freecount_9httptools_6parser_10url_parser_URL > 0) & (t->tp_basicsize == sizeof(struct __pyx_obj_9httptools_6parser_10url_parser_URL)) & ((t->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)) == 0))) { + o = (PyObject*)__pyx_freelist_9httptools_6parser_10url_parser_URL[--__pyx_freecount_9httptools_6parser_10url_parser_URL]; + memset(o, 0, sizeof(struct __pyx_obj_9httptools_6parser_10url_parser_URL)); + (void) PyObject_INIT(o, t); + PyObject_GC_Track(o); + } else { + if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { + o = (*t->tp_alloc)(t, 0); + } else { + o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); + } + if (unlikely(!o)) return 0; + } + p = ((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)o); + p->schema = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->host = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->port = Py_None; Py_INCREF(Py_None); + p->path = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->query = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->fragment = ((PyObject*)Py_None); Py_INCREF(Py_None); + p->userinfo = ((PyObject*)Py_None); Py_INCREF(Py_None); + if (unlikely(__pyx_pw_9httptools_6parser_10url_parser_3URL_1__cinit__(o, a, k) < 0)) goto bad; + return o; + bad: + Py_DECREF(o); o = 0; + return NULL; +} + +static void __pyx_tp_dealloc_9httptools_6parser_10url_parser_URL(PyObject *o) { + struct __pyx_obj_9httptools_6parser_10url_parser_URL *p = (struct __pyx_obj_9httptools_6parser_10url_parser_URL *)o; + #if CYTHON_USE_TP_FINALIZE + if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { + if (PyObject_CallFinalizerFromDealloc(o)) return; + } + #endif + PyObject_GC_UnTrack(o); + Py_CLEAR(p->schema); + Py_CLEAR(p->host); + Py_CLEAR(p->port); + Py_CLEAR(p->path); + Py_CLEAR(p->query); + Py_CLEAR(p->fragment); + Py_CLEAR(p->userinfo); + if (CYTHON_COMPILING_IN_CPYTHON && ((__pyx_freecount_9httptools_6parser_10url_parser_URL < 250) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_9httptools_6parser_10url_parser_URL)) & ((Py_TYPE(o)->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)) == 0))) { + __pyx_freelist_9httptools_6parser_10url_parser_URL[__pyx_freecount_9httptools_6parser_10url_parser_URL++] = ((struct __pyx_obj_9httptools_6parser_10url_parser_URL *)o); + } else { + (*Py_TYPE(o)->tp_free)(o); + } +} + +static int __pyx_tp_traverse_9httptools_6parser_10url_parser_URL(PyObject *o, visitproc v, void *a) { + int e; + struct __pyx_obj_9httptools_6parser_10url_parser_URL *p = (struct __pyx_obj_9httptools_6parser_10url_parser_URL *)o; + if (p->port) { + e = (*v)(p->port, a); if (e) return e; + } + return 0; +} + +static int __pyx_tp_clear_9httptools_6parser_10url_parser_URL(PyObject *o) { + PyObject* tmp; + struct __pyx_obj_9httptools_6parser_10url_parser_URL *p = (struct __pyx_obj_9httptools_6parser_10url_parser_URL *)o; + tmp = ((PyObject*)p->port); + p->port = Py_None; Py_INCREF(Py_None); + Py_XDECREF(tmp); + return 0; +} + +static PyObject *__pyx_getprop_9httptools_6parser_10url_parser_3URL_schema(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_9httptools_6parser_10url_parser_3URL_6schema_1__get__(o); +} + +static PyObject *__pyx_getprop_9httptools_6parser_10url_parser_3URL_host(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_9httptools_6parser_10url_parser_3URL_4host_1__get__(o); +} + +static PyObject *__pyx_getprop_9httptools_6parser_10url_parser_3URL_port(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_9httptools_6parser_10url_parser_3URL_4port_1__get__(o); +} + +static PyObject *__pyx_getprop_9httptools_6parser_10url_parser_3URL_path(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_9httptools_6parser_10url_parser_3URL_4path_1__get__(o); +} + +static PyObject *__pyx_getprop_9httptools_6parser_10url_parser_3URL_query(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_9httptools_6parser_10url_parser_3URL_5query_1__get__(o); +} + +static PyObject *__pyx_getprop_9httptools_6parser_10url_parser_3URL_fragment(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_9httptools_6parser_10url_parser_3URL_8fragment_1__get__(o); +} + +static PyObject *__pyx_getprop_9httptools_6parser_10url_parser_3URL_userinfo(PyObject *o, CYTHON_UNUSED void *x) { + return __pyx_pw_9httptools_6parser_10url_parser_3URL_8userinfo_1__get__(o); +} + +static PyMethodDef __pyx_methods_9httptools_6parser_10url_parser_URL[] = { + {"__reduce_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_10url_parser_3URL_5__reduce_cython__, METH_NOARGS, 0}, + {"__setstate_cython__", (PyCFunction)__pyx_pw_9httptools_6parser_10url_parser_3URL_7__setstate_cython__, METH_O, 0}, + {0, 0, 0, 0} +}; + +static struct PyGetSetDef __pyx_getsets_9httptools_6parser_10url_parser_URL[] = { + {(char *)"schema", __pyx_getprop_9httptools_6parser_10url_parser_3URL_schema, 0, (char *)0, 0}, + {(char *)"host", __pyx_getprop_9httptools_6parser_10url_parser_3URL_host, 0, (char *)0, 0}, + {(char *)"port", __pyx_getprop_9httptools_6parser_10url_parser_3URL_port, 0, (char *)0, 0}, + {(char *)"path", __pyx_getprop_9httptools_6parser_10url_parser_3URL_path, 0, (char *)0, 0}, + {(char *)"query", __pyx_getprop_9httptools_6parser_10url_parser_3URL_query, 0, (char *)0, 0}, + {(char *)"fragment", __pyx_getprop_9httptools_6parser_10url_parser_3URL_fragment, 0, (char *)0, 0}, + {(char *)"userinfo", __pyx_getprop_9httptools_6parser_10url_parser_3URL_userinfo, 0, (char *)0, 0}, + {0, 0, 0, 0, 0} +}; + +static PyTypeObject __pyx_type_9httptools_6parser_10url_parser_URL = { + PyVarObject_HEAD_INIT(0, 0) + "httptools.parser.url_parser.URL", /*tp_name*/ + sizeof(struct __pyx_obj_9httptools_6parser_10url_parser_URL), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + __pyx_tp_dealloc_9httptools_6parser_10url_parser_URL, /*tp_dealloc*/ + #if PY_VERSION_HEX < 0x030800b4 + 0, /*tp_print*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 + 0, /*tp_vectorcall_offset*/ + #endif + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + #if PY_MAJOR_VERSION < 3 + 0, /*tp_compare*/ + #endif + #if PY_MAJOR_VERSION >= 3 + 0, /*tp_as_async*/ + #endif + __pyx_pw_9httptools_6parser_10url_parser_3URL_3__repr__, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + 0, /*tp_doc*/ + __pyx_tp_traverse_9httptools_6parser_10url_parser_URL, /*tp_traverse*/ + __pyx_tp_clear_9httptools_6parser_10url_parser_URL, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + __pyx_methods_9httptools_6parser_10url_parser_URL, /*tp_methods*/ + 0, /*tp_members*/ + __pyx_getsets_9httptools_6parser_10url_parser_URL, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + 0, /*tp_alloc*/ + __pyx_tp_new_9httptools_6parser_10url_parser_URL, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ + 0, /*tp_bases*/ + 0, /*tp_mro*/ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0, /*tp_weaklist*/ + 0, /*tp_del*/ + 0, /*tp_version_tag*/ + #if PY_VERSION_HEX >= 0x030400a1 + 0, /*tp_finalize*/ + #endif + #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) + 0, /*tp_vectorcall*/ + #endif + #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, /*tp_print*/ + #endif + #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 + 0, /*tp_pypy_flags*/ + #endif +}; + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_url_parser(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_url_parser}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "url_parser", + 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_n_s_HttpParserInvalidURLError, __pyx_k_HttpParserInvalidURLError, sizeof(__pyx_k_HttpParserInvalidURLError), 0, 0, 1, 1}, + {&__pyx_n_s_TypeError, __pyx_k_TypeError, sizeof(__pyx_k_TypeError), 0, 0, 1, 1}, + {&__pyx_n_s_URL, __pyx_k_URL, sizeof(__pyx_k_URL), 0, 0, 1, 1}, + {&__pyx_kp_u_URL_schema_r_host_r_port_r_path, __pyx_k_URL_schema_r_host_r_port_r_path, sizeof(__pyx_k_URL_schema_r_host_r_port_r_path), 0, 1, 0, 0}, + {&__pyx_n_s_all, __pyx_k_all, sizeof(__pyx_k_all), 0, 0, 1, 1}, + {&__pyx_n_s_buf_data, __pyx_k_buf_data, sizeof(__pyx_k_buf_data), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_errors, __pyx_k_errors, sizeof(__pyx_k_errors), 0, 0, 1, 1}, + {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1}, + {&__pyx_n_s_fragment, __pyx_k_fragment, sizeof(__pyx_k_fragment), 0, 0, 1, 1}, + {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1}, + {&__pyx_n_s_host, __pyx_k_host, sizeof(__pyx_k_host), 0, 0, 1, 1}, + {&__pyx_n_s_httptools_parser_url_parser, __pyx_k_httptools_parser_url_parser, sizeof(__pyx_k_httptools_parser_url_parser), 0, 0, 1, 1}, + {&__pyx_kp_s_httptools_parser_url_parser_pyx, __pyx_k_httptools_parser_url_parser_pyx, sizeof(__pyx_k_httptools_parser_url_parser_pyx), 0, 0, 1, 0}, + {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, + {&__pyx_kp_u_invalid_url_r, __pyx_k_invalid_url_r, sizeof(__pyx_k_invalid_url_r), 0, 1, 0, 0}, + {&__pyx_n_s_ln, __pyx_k_ln, sizeof(__pyx_k_ln), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_kp_s_no_default___reduce___due_to_non, __pyx_k_no_default___reduce___due_to_non, sizeof(__pyx_k_no_default___reduce___due_to_non), 0, 0, 1, 0}, + {&__pyx_n_s_off, __pyx_k_off, sizeof(__pyx_k_off), 0, 0, 1, 1}, + {&__pyx_n_s_parse_url, __pyx_k_parse_url, sizeof(__pyx_k_parse_url), 0, 0, 1, 1}, + {&__pyx_n_u_parse_url, __pyx_k_parse_url, sizeof(__pyx_k_parse_url), 0, 1, 0, 1}, + {&__pyx_n_s_parsed, __pyx_k_parsed, sizeof(__pyx_k_parsed), 0, 0, 1, 1}, + {&__pyx_n_s_path, __pyx_k_path, sizeof(__pyx_k_path), 0, 0, 1, 1}, + {&__pyx_n_s_port, __pyx_k_port, sizeof(__pyx_k_port), 0, 0, 1, 1}, + {&__pyx_n_s_py_buf, __pyx_k_py_buf, sizeof(__pyx_k_py_buf), 0, 0, 1, 1}, + {&__pyx_n_s_query, __pyx_k_query, sizeof(__pyx_k_query), 0, 0, 1, 1}, + {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1}, + {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, + {&__pyx_n_s_res, __pyx_k_res, sizeof(__pyx_k_res), 0, 0, 1, 1}, + {&__pyx_n_s_result, __pyx_k_result, sizeof(__pyx_k_result), 0, 0, 1, 1}, + {&__pyx_n_s_schema, __pyx_k_schema, sizeof(__pyx_k_schema), 0, 0, 1, 1}, + {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, + {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_url, __pyx_k_url, sizeof(__pyx_k_url), 0, 0, 1, 1}, + {&__pyx_n_s_userinfo, __pyx_k_userinfo, sizeof(__pyx_k_userinfo), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(0, 2, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "(tree fragment)":2 + * def __reduce_cython__(self): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + */ + __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 2, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple_); + __Pyx_GIVEREF(__pyx_tuple_); + + /* "(tree fragment)":4 + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") + * def __setstate_cython__(self, __pyx_state): + * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< + */ + __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 4, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__2); + __Pyx_GIVEREF(__pyx_tuple__2); + + /* "httptools/parser/url_parser.pyx":13 + * from . cimport url_cparser as uparser + * + * __all__ = ('parse_url',) # <<<<<<<<<<<<<< + * + * @cython.freelist(250) + */ + __pyx_tuple__3 = PyTuple_Pack(1, __pyx_n_u_parse_url); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 13, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__3); + __Pyx_GIVEREF(__pyx_tuple__3); + + /* "httptools/parser/url_parser.pyx":43 + * + * + * def parse_url(url): # <<<<<<<<<<<<<< + * cdef: + * Py_buffer py_buf + */ + __pyx_tuple__4 = PyTuple_Pack(15, __pyx_n_s_url, __pyx_n_s_py_buf, __pyx_n_s_buf_data, __pyx_n_s_parsed, __pyx_n_s_res, __pyx_n_s_schema, __pyx_n_s_host, __pyx_n_s_port, __pyx_n_s_path, __pyx_n_s_query, __pyx_n_s_fragment, __pyx_n_s_userinfo, __pyx_n_s_result, __pyx_n_s_off, __pyx_n_s_ln); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 43, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__4); + __Pyx_GIVEREF(__pyx_tuple__4); + __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(1, 0, 15, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_httptools_parser_url_parser_pyx, __pyx_n_s_parse_url, 43, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(1, 43, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(1, 1, __pyx_L1_error); + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + if (PyType_Ready(&__pyx_type_9httptools_6parser_10url_parser_URL) < 0) __PYX_ERR(1, 16, __pyx_L1_error) + #if PY_VERSION_HEX < 0x030800B1 + __pyx_type_9httptools_6parser_10url_parser_URL.tp_print = 0; + #endif + if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9httptools_6parser_10url_parser_URL.tp_dictoffset && __pyx_type_9httptools_6parser_10url_parser_URL.tp_getattro == PyObject_GenericGetAttr)) { + __pyx_type_9httptools_6parser_10url_parser_URL.tp_getattro = __Pyx_PyObject_GenericGetAttr; + } + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_URL, (PyObject *)&__pyx_type_9httptools_6parser_10url_parser_URL) < 0) __PYX_ERR(1, 16, __pyx_L1_error) + if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9httptools_6parser_10url_parser_URL) < 0) __PYX_ERR(1, 16, __pyx_L1_error) + __pyx_ptype_9httptools_6parser_10url_parser_URL = &__pyx_type_9httptools_6parser_10url_parser_URL; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(3, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(4, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(4, 15, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#ifndef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#elif PY_MAJOR_VERSION < 3 +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" void +#else +#define __Pyx_PyMODINIT_FUNC void +#endif +#else +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyObject * +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initurl_parser(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initurl_parser(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_url_parser(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_url_parser(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_url_parser(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'url_parser' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_url_parser(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(1, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(1, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + PyEval_InitThreads(); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("url_parser", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(1, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(1, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(1, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(1, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main_httptools__parser__url_parser) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(1, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "httptools.parser.url_parser")) { + if (unlikely(PyDict_SetItemString(modules, "httptools.parser.url_parser", __pyx_m) < 0)) __PYX_ERR(1, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + if (unlikely(__Pyx_modinit_type_init_code() < 0)) __PYX_ERR(1, 1, __pyx_L1_error) + if (unlikely(__Pyx_modinit_type_import_code() < 0)) __PYX_ERR(1, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(1, 1, __pyx_L1_error) + #endif + + /* "httptools/parser/url_parser.pyx":8 + * Py_buffer + * + * from .errors import HttpParserInvalidURLError # <<<<<<<<<<<<<< + * + * cimport cython + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_n_s_HttpParserInvalidURLError); + __Pyx_GIVEREF(__pyx_n_s_HttpParserInvalidURLError); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_HttpParserInvalidURLError); + __pyx_t_2 = __Pyx_Import(__pyx_n_s_errors, __pyx_t_1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_HttpParserInvalidURLError); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_HttpParserInvalidURLError, __pyx_t_1) < 0) __PYX_ERR(1, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "httptools/parser/url_parser.pyx":13 + * from . cimport url_cparser as uparser + * + * __all__ = ('parse_url',) # <<<<<<<<<<<<<< + * + * @cython.freelist(250) + */ + if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_tuple__3) < 0) __PYX_ERR(1, 13, __pyx_L1_error) + + /* "httptools/parser/url_parser.pyx":43 + * + * + * def parse_url(url): # <<<<<<<<<<<<<< + * cdef: + * Py_buffer py_buf + */ + __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9httptools_6parser_10url_parser_1parse_url, NULL, __pyx_n_s_httptools_parser_url_parser); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 43, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_parse_url, __pyx_t_2) < 0) __PYX_ERR(1, 43, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "httptools/parser/url_parser.pyx":1 + * #cython: language_level=3 # <<<<<<<<<<<<<< + * + * from __future__ import print_function + */ + __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init httptools.parser.url_parser", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init httptools.parser.url_parser"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* ArgTypeTest */ +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) +{ + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + else if (exact) { + #if PY_MAJOR_VERSION == 2 + if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; + #endif + } + else { + if (likely(__Pyx_TypeCheck(obj, type))) return 1; + } + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); + return 0; +} + +/* PyFunctionFastCall */ +#if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyCFunctionFastCall */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = Py_TYPE(func)->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* RaiseException */ +#if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, + CYTHON_UNUSED PyObject *cause) { + __Pyx_PyThreadState_declare + Py_XINCREF(type); + if (!value || value == Py_None) + value = NULL; + else + Py_INCREF(value); + if (!tb || tb == Py_None) + tb = NULL; + else { + Py_INCREF(tb); + if (!PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + } + if (PyType_Check(type)) { +#if CYTHON_COMPILING_IN_PYPY + if (!value) { + Py_INCREF(Py_None); + value = Py_None; + } +#endif + PyErr_NormalizeException(&type, &value, &tb); + } else { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + value = type; + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + } + __Pyx_PyThreadState_assign + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} +#else +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if CYTHON_COMPILING_IN_PYPY + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#else + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} +#endif + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ +#if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* PyObjectCall2Args */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { + PyObject *args, *result = NULL; + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyFunction_FastCall(function, args, 2); + } + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyCFunction_FastCall(function, args, 2); + } + #endif + args = PyTuple_New(2); + if (unlikely(!args)) goto done; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + Py_INCREF(function); + result = __Pyx_PyObject_Call(function, args, NULL); + Py_DECREF(args); + Py_DECREF(function); +done: + return result; +} + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallOneArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (__Pyx_PyFastCFunction_Check(func)) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* GetException */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) +#endif +{ + PyObject *local_type, *local_value, *local_tb; +#if CYTHON_FAST_THREAD_STATE + PyObject *tmp_type, *tmp_value, *tmp_tb; + local_type = tstate->curexc_type; + local_value = tstate->curexc_value; + local_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#else + PyErr_Fetch(&local_type, &local_value, &local_tb); +#endif + PyErr_NormalizeException(&local_type, &local_value, &local_tb); +#if CYTHON_FAST_THREAD_STATE + if (unlikely(tstate->curexc_type)) +#else + if (unlikely(PyErr_Occurred())) +#endif + goto bad; + #if PY_MAJOR_VERSION >= 3 + if (local_tb) { + if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) + goto bad; + } + #endif + Py_XINCREF(local_tb); + Py_XINCREF(local_type); + Py_XINCREF(local_value); + *type = local_type; + *value = local_value; + *tb = local_tb; +#if CYTHON_FAST_THREAD_STATE + #if CYTHON_USE_EXC_INFO_STACK + { + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = local_type; + exc_info->exc_value = local_value; + exc_info->exc_traceback = local_tb; + } + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = local_type; + tstate->exc_value = local_value; + tstate->exc_traceback = local_tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#else + PyErr_SetExcInfo(local_type, local_value, local_tb); +#endif + return 0; +bad: + *type = 0; + *value = 0; + *tb = 0; + Py_XDECREF(local_type); + Py_XDECREF(local_value); + Py_XDECREF(local_tb); + return -1; +} + +/* SwapException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = *type; + exc_info->exc_value = *value; + exc_info->exc_traceback = *tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = *type; + tstate->exc_value = *value; + tstate->exc_traceback = *tb; + #endif + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#else +static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb); + PyErr_SetExcInfo(*type, *value, *tb); + *type = tmp_type; + *value = tmp_value; + *tb = tmp_tb; +} +#endif + +/* GetTopmostException */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* SaveResetException */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + *type = exc_info->exc_type; + *value = exc_info->exc_value; + *tb = exc_info->exc_traceback; + #else + *type = tstate->exc_type; + *value = tstate->exc_value; + *tb = tstate->exc_traceback; + #endif + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); +} +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_traceback = tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = type; + tstate->exc_value = value; + tstate->exc_traceback = tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +#endif + +/* PyObject_GenericGetAttrNoDict */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, attr_name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(attr_name)); +#endif + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { + PyObject *descr; + PyTypeObject *tp = Py_TYPE(obj); + if (unlikely(!PyString_Check(attr_name))) { + return PyObject_GenericGetAttr(obj, attr_name); + } + assert(!tp->tp_dictoffset); + descr = _PyType_Lookup(tp, attr_name); + if (unlikely(!descr)) { + return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); + } + Py_INCREF(descr); + #if PY_MAJOR_VERSION < 3 + if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) + #endif + { + descrgetfunc f = Py_TYPE(descr)->tp_descr_get; + if (unlikely(f)) { + PyObject *res = f(descr, obj, (PyObject *)tp); + Py_DECREF(descr); + return res; + } + } + return descr; +} +#endif + +/* PyObject_GenericGetAttr */ +#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 +static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { + if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { + return PyObject_GenericGetAttr(obj, attr_name); + } + return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); +} +#endif + +/* PyErrExceptionMatches */ +#if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; icurexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; + if (unlikely(PyTuple_Check(err))) + return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); +} +#endif + +/* PyObjectGetAttrStrNoError */ +static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) + __Pyx_PyErr_Clear(); +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { + PyObject *result; +#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1 + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { + return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); + } +#endif + result = __Pyx_PyObject_GetAttrStr(obj, attr_name); + if (unlikely(!result)) { + __Pyx_PyObject_GetAttrStr_ClearAttributeError(); + } + return result; +} + +/* SetupReduce */ +static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { + int ret; + PyObject *name_attr; + name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name); + if (likely(name_attr)) { + ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); + } else { + ret = -1; + } + if (unlikely(ret < 0)) { + PyErr_Clear(); + ret = 0; + } + Py_XDECREF(name_attr); + return ret; +} +static int __Pyx_setup_reduce(PyObject* type_obj) { + int ret = 0; + PyObject *object_reduce = NULL; + PyObject *object_reduce_ex = NULL; + PyObject *reduce = NULL; + PyObject *reduce_ex = NULL; + PyObject *reduce_cython = NULL; + PyObject *setstate = NULL; + PyObject *setstate_cython = NULL; +#if CYTHON_USE_PYTYPE_LOOKUP + if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; +#else + if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto __PYX_GOOD; +#endif +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#else + object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; +#endif + reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_ex); if (unlikely(!reduce_ex)) goto __PYX_BAD; + if (reduce_ex == object_reduce_ex) { +#if CYTHON_USE_PYTYPE_LOOKUP + object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#else + object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; +#endif + reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto __PYX_BAD; + if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) { + reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_reduce_cython); + if (likely(reduce_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (reduce == object_reduce || PyErr_Occurred()) { + goto __PYX_BAD; + } + setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate); + if (!setstate) PyErr_Clear(); + if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) { + setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_setstate_cython); + if (likely(setstate_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (!setstate || PyErr_Occurred()) { + goto __PYX_BAD; + } + } + PyType_Modified((PyTypeObject*)type_obj); + } + } + goto __PYX_GOOD; +__PYX_BAD: + if (!PyErr_Occurred()) + PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name); + ret = -1; +__PYX_GOOD: +#if !CYTHON_USE_PYTYPE_LOOKUP + Py_XDECREF(object_reduce); + Py_XDECREF(object_reduce_ex); +#endif + Py_XDECREF(reduce); + Py_XDECREF(reduce_ex); + Py_XDECREF(reduce_cython); + Py_XDECREF(setstate); + Py_XDECREF(setstate_cython); + return ret; +} + +/* TypeImport */ +#ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, + size_t size, enum __Pyx_ImportType_CheckSize check_size) +{ + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if ((size_t)basicsize < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* Import */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + #if PY_MAJOR_VERSION < 3 + PyObject *py_import; + py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); + if (!py_import) + goto bad; + #endif + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + { + #if PY_MAJOR_VERSION >= 3 + if (level == -1) { + if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, 1); + if (!module) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + goto bad; + PyErr_Clear(); + } + } + level = 0; + } + #endif + if (!module) { + #if PY_MAJOR_VERSION < 3 + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, level); + #endif + } + } +bad: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_import); + #endif + Py_XDECREF(empty_list); + Py_XDECREF(empty_dict); + return module; +} + +/* ImportFrom */ +static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { + PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); + if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_ImportError, + #if PY_MAJOR_VERSION < 3 + "cannot import name %.230s", PyString_AS_STRING(name)); + #else + "cannot import name %S", name); + #endif + } + return value; +} + +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; + py_srcfile = PyString_FromString(filename); + if (!py_srcfile) goto bad; + #endif + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + #endif + } + #if PY_MAJOR_VERSION < 3 + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline + return py_code; +bad: + Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint16_t(uint16_t value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const uint16_t neg_one = (uint16_t) -1, const_zero = (uint16_t) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(uint16_t) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(uint16_t) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint16_t) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(uint16_t) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(uint16_t) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(uint16_t), + little, !is_unsigned); + } +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; ip) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/url_parser.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/httptools/parser/url_parser.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..ba98dd721be1c855b9f6a925348720012e215f23 GIT binary patch literal 39424 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
S076 zLQ-J&-PJYgtJ&Cjn|cx{bA2B0zDuVq5OoRl5Ekq2Tu(V{ER3LpWp|kQ95)}CnJCX? z*Jptp)n$umd_1bt&h=Cg6F8fWke(2$G=BWukapwnm1Aq0$;WKn89 z3??r%nR=g%-~zVKeqKg`~-bT%0iDNRA`BDp&b%JVxTLm9|EccGDU31D?fX zVq{nk>2YwI>sjSrz1ri`xx71X(fmAD<}@yIljL^ixNC8w3Y{o*bKyZ+sYtI?%G?TB zBD!qhF2k9FuV#ZAr`#AtcSvhJYiluCN=tJVEty~F%+H%TJ%iJ{O+txE1r1*--QE{= zd*IXH$ftsi?~&=IPEVHHr8U*%m8&5~9CP5bV!a!O&FgT{nU~~E(z86(>neRU)%-Td z^nMta2J5g&Q%FFPbc5vf)WQA1U5tJiqfsB>VaM59Ic04vE%m09`jjc+>}*Qa)G1S^ z@P^EyHkNv!YyZ8E{f5lHTh$5{?Y2D9vURi)eDLwL|$FWaW-&Y2sXY%0t z{^R^SJwxC}(uxeH2t4~&;FYc8^a{QLZ?d3Q{1tfkJKwAw-mk#33%vTTz$*}VJHG-i zvhDvYoF&>TjpcmC3_var`CgGv`{w^6A90?=_9v*E-oIZ(W2es70L12>a6awL91h67 zB05xkUO`_TPy&0(tiJ{%UlH|={@3uXC^%F?Zhy(Qr*Zl{0uEJ7Pe1Tve}26GqI~r7 z1L1+x{`3as|Ifx-4sg0VH*+|4ARz@|z z$*12(*OLl?w@=_*q3?oThp4wj;Klc&hKRr`5cFC$a{jIw0?#J!q%9l|yR!X1f}SMs zdWBqu!s`%tHbHMF{@Mgyv7kq1qWwOi-h-mOUV&%qhlGg0YZvtDMSI5$ftMukngyQi z3Ot^WEbtBpIpd_J|3}nYB=B|$yb=Ae!gi-kw4+eqMGwH!+mRvYrF}*J77IMPkjqeV zmVV0n^?<-*2Y!)t3k5tN_L#})`@y0fj4T1cGv}8fv9&V zea;ei)4!sIoO}AIN9_o6l>rsc`OXqLM`u?5qKPG`B z?Ba~Zxex9{)C2x)49@HtK>`zfIi3`R;Y&(yiEt0#^QpKigLL>D(mfM!X9nTOvwb@A z|8^SQO+Y%qBX}whhHoTIoXF2J4*=@t`UG=v7QX{H1WWNehj8SXJe}45{5J53bb`Oa z6Vrq^;GElWHv{1U!0+R+A>0i3>I|HPA>0DEd8Q=ILbx9A1H9u`h;R=e{hkl;-vjv9 z**qM1_D*N=f5TG`e1aozw*Dx>k>}@;XY6$LKFN;14Fw#6U&Heb!UP-fe1tH;UyE=j z;FdXP%R{IGaCa`}GxALQA4sD!^c3I_)X&lhejkqu=>&g@rx;;^FXQndOz=3KdW72n zopW*b1>wlEaymn|$ddFT(g~K~X+xM`z7snagb!GH7x+gw@?1Oe+?&qBd+&zKw{e)_ zf;I0sK5!Ucdw@Khk&4p@zIYcIl)=ht-Reb++h1JVgD!m|%yg2i}_BkWxaT1%k^ z2os!u^XZQewgcXW$Fv=|fCuo@p??XUxJQx_k=_RAx)n= zB9HE;eY1Zd7Mpcv-P$Vsrugg$Q`0jh*gUv1Uxv35W>3I5#gwcGHhN#6tfUH?VY4S} z@YGJY^A2;uEW8fjS-T4F=YT+U?QFd9QazL36t11JwzAY$Q(IH6Ou>EhnI*Mr)7MR% zfQ#nUmF3t86z5XBHX?P4P79Gic>KRQ$;-O*3-@LzNf7|}h m{+|6w&n7=x{A|Uu_0Mj9cIUIZo^5`1-?ImvMRWg;`TRe{E!2nr literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/LICENSE new file mode 100644 index 00000000..411ce482 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017, 2018, 2019, 2020, 2021 Samuel Colvin 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/METADATA new file mode 100644 index 00000000..9036ed80 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/METADATA @@ -0,0 +1,1221 @@ +Metadata-Version: 2.1 +Name: pydantic +Version: 1.10.1 +Summary: Data validation and settings management using python type hints +Home-page: https://github.com/pydantic/pydantic +Author: Samuel Colvin +Author-email: s@muelcolvin.com +License: MIT +Classifier: Development Status :: 5 - Production/Stable +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: Unix +Classifier: Operating System :: POSIX :: Linux +Classifier: Environment :: Console +Classifier: Environment :: MacOS X +Classifier: Framework :: Hypothesis +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Internet +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: typing-extensions (>=4.1.0) +Provides-Extra: dotenv +Requires-Dist: python-dotenv (>=0.10.4) ; extra == 'dotenv' +Provides-Extra: email +Requires-Dist: email-validator (>=1.0.3) ; extra == 'email' + +# pydantic + +[![CI](https://github.com/pydantic/pydantic/workflows/CI/badge.svg?event=push)](https://github.com/pydantic/pydantic/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) +[![Coverage](https://coverage-badge.samuelcolvin.workers.dev/pydantic/pydantic.svg)](https://coverage-badge.samuelcolvin.workers.dev/redirect/pydantic/pydantic) +[![pypi](https://img.shields.io/pypi/v/pydantic.svg)](https://pypi.python.org/pypi/pydantic) +[![CondaForge](https://img.shields.io/conda/v/conda-forge/pydantic.svg)](https://anaconda.org/conda-forge/pydantic) +[![downloads](https://pepy.tech/badge/pydantic/month)](https://pepy.tech/project/pydantic) +[![versions](https://img.shields.io/pypi/pyversions/pydantic.svg)](https://github.com/pydantic/pydantic) +[![license](https://img.shields.io/github/license/pydantic/pydantic.svg)](https://github.com/pydantic/pydantic/blob/main/LICENSE) + +Data validation and settings management using Python type hints. + +Fast and extensible, *pydantic* plays nicely with your linters/IDE/brain. +Define how data should be in pure, canonical Python 3.7+; validate it with *pydantic*. + +## Help + +See [documentation](https://pydantic-docs.helpmanual.io/) for more details. + +## Installation + +Install using `pip install -U pydantic` or `conda install pydantic -c conda-forge`. +For more installation options to make *pydantic* even faster, +see the [Install](https://pydantic-docs.helpmanual.io/install/) section in the documentation. + +## A Simple Example + +```py +from datetime import datetime +from typing import List, Optional +from pydantic import BaseModel + +class User(BaseModel): + id: int + name = 'John Doe' + signup_ts: Optional[datetime] = None + friends: List[int] = [] + +external_data = {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']} +user = User(**external_data) +print(user) +#> User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3] +print(user.id) +#> 123 +``` + +## Contributing + +For guidance on setting up a development environment and how to make a +contribution to *pydantic*, see +[Contributing to Pydantic](https://pydantic-docs.helpmanual.io/contributing/). + +## Reporting a Security Vulnerability + +See our [security policy](https://github.com/pydantic/pydantic/security/policy). + + +## v1.10.1 (2022-08-31) + +* Add `__hash__` method to `pydancic.color.Color` class, [#4454](https://github.com/pydantic/pydantic/issues/4454) by [@czaki](https://github.com/czaki) + +## v1.10.0 (2022-08-30) + +* Refactor the whole _pydantic_ `dataclass` decorator to really act like its standard lib equivalent. + It hence keeps `__eq__`, `__hash__`, ... and makes comparison with its non-validated version possible. + It also fixes usage of `frozen` dataclasses in fields and usage of `default_factory` in nested dataclasses. + The support of `Config.extra` has been added. + Finally, config customization directly via a `dict` is now possible, [#2557](https://github.com/pydantic/pydantic/issues/2557) by [@PrettyWood](https://github.com/PrettyWood) +

+ **BREAKING CHANGES:** + - The `compiled` boolean (whether _pydantic_ is compiled with cython) has been moved from `main.py` to `version.py` + - Now that `Config.extra` is supported, `dataclass` ignores by default extra arguments (like `BaseModel`) +* Fix PEP487 `__set_name__` protocol in `BaseModel` for PrivateAttrs, [#4407](https://github.com/pydantic/pydantic/issues/4407) by [@tlambert03](https://github.com/tlambert03) +* Allow for custom parsing of environment variables via `parse_env_var` in `Config`, [#4406](https://github.com/pydantic/pydantic/issues/4406) by [@acmiyaguchi](https://github.com/acmiyaguchi) +* Rename `master` to `main`, [#4405](https://github.com/pydantic/pydantic/issues/4405) by [@hramezani](https://github.com/hramezani) +* Fix `StrictStr` does not raise `ValidationError` when `max_length` is present in `Field`, [#4388](https://github.com/pydantic/pydantic/issues/4388) by [@hramezani](https://github.com/hramezani) +* Make `SecretStr` and `SecretBytes` hashable, [#4387](https://github.com/pydantic/pydantic/issues/4387) by [@chbndrhnns](https://github.com/chbndrhnns) +* Fix `StrictBytes` does not raise `ValidationError` when `max_length` is present in `Field`, [#4380](https://github.com/pydantic/pydantic/issues/4380) by [@JeanArhancet](https://github.com/JeanArhancet) +* Add support for bare `type`, [#4375](https://github.com/pydantic/pydantic/issues/4375) by [@hramezani](https://github.com/hramezani) +* Support Python 3.11, including binaries for 3.11 in PyPI, [#4374](https://github.com/pydantic/pydantic/issues/4374) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for `re.Pattern`, [#4366](https://github.com/pydantic/pydantic/issues/4366) by [@hramezani](https://github.com/hramezani) +* Fix `__post_init_post_parse__` is incorrectly passed keyword arguments when no `__post_init__` is defined, [#4361](https://github.com/pydantic/pydantic/issues/4361) by [@hramezani](https://github.com/hramezani) +* Fix implicitly importing `ForwardRef` and `Callable` from `pydantic.typing` instead of `typing` and also expose `MappingIntStrAny`, [#4358](https://github.com/pydantic/pydantic/issues/4358) by [@aminalaee](https://github.com/aminalaee) +* remove `Any` types from the `dataclass` decorator so it can be used with the `disallow_any_expr` mypy option, [#4356](https://github.com/pydantic/pydantic/issues/4356) by [@DetachHead](https://github.com/DetachHead) +* moved repo to `pydantic/pydantic`, [#4348](https://github.com/pydantic/pydantic/issues/4348) by [@yezz123](https://github.com/yezz123) +* fix "extra fields not permitted" error when dataclass with `Extra.forbid` is validated multiple times, [#4343](https://github.com/pydantic/pydantic/issues/4343) by [@detachhead](https://github.com/detachhead) +* Add Python 3.9 and 3.10 examples to docs, [#4339](https://github.com/pydantic/pydantic/issues/4339) by [@Bobronium](https://github.com/Bobronium) +* Discriminated union models now use `oneOf` instead of `anyOf` when generating OpenAPI schema definitions, [#4335](https://github.com/pydantic/pydantic/issues/4335) by [@MaxwellPayne](https://github.com/MaxwellPayne) +* Allow type checkers to infer inner type of `Json` type. `Json[list[str]]` will be now inferred as `list[str]`, + `Json[Any]` should be used instead of plain `Json`. + Runtime behaviour is not changed, [#4332](https://github.com/pydantic/pydantic/issues/4332) by [@Bobronium](https://github.com/Bobronium) +* Allow empty string aliases by using a `alias is not None` check, rather than `bool(alias)`, [#4253](https://github.com/pydantic/pydantic/issues/4253) by [@sergeytsaplin](https://github.com/sergeytsaplin) +* Update `ForwardRef`s in `Field.outer_type_`, [#4249](https://github.com/pydantic/pydantic/issues/4249) by [@JacobHayes](https://github.com/JacobHayes) +* The use of `__dataclass_transform__` has been replaced by `typing_extensions.dataclass_transform`, which is the preferred way to mark pydantic models as a dataclass under [PEP 681](https://peps.python.org/pep-0681/), [#4241](https://github.com/pydantic/pydantic/issues/4241) by [@multimeric](https://github.com/multimeric) +* Use parent model's `Config` when validating nested `NamedTuple` fields, [#4219](https://github.com/pydantic/pydantic/issues/4219) by [@synek](https://github.com/synek) +* Update `BaseModel.construct` to work with aliased Fields, [#4192](https://github.com/pydantic/pydantic/issues/4192) by [@kylebamos](https://github.com/kylebamos) +* Catch certain raised errors in `smart_deepcopy` and revert to `deepcopy` if so, [#4184](https://github.com/pydantic/pydantic/issues/4184) by [@coneybeare](https://github.com/coneybeare) +* Add `Config.anystr_upper` and `to_upper` kwarg to constr and conbytes, [#4165](https://github.com/pydantic/pydantic/issues/4165) by [@satheler](https://github.com/satheler) +* Fix JSON schema for `set` and `frozenset` when they include default values, [#4155](https://github.com/pydantic/pydantic/issues/4155) by [@aminalaee](https://github.com/aminalaee) +* Teach the mypy plugin that methods decorated by `@validator` are classmethods, [#4102](https://github.com/pydantic/pydantic/issues/4102) by [@DMRobertson](https://github.com/DMRobertson) +* Improve mypy plugin's ability to detect required fields, [#4086](https://github.com/pydantic/pydantic/issues/4086) by [@richardxia](https://github.com/richardxia) +* Support fields of type `Type[]` in schema, [#4051](https://github.com/pydantic/pydantic/issues/4051) by [@aminalaee](https://github.com/aminalaee) +* Add `default` value in JSON Schema when `const=True`, [#4031](https://github.com/pydantic/pydantic/issues/4031) by [@aminalaee](https://github.com/aminalaee) +* Adds reserved word check to signature generation logic, [#4011](https://github.com/pydantic/pydantic/issues/4011) by [@strue36](https://github.com/strue36) +* Fix Json strategy failure for the complex nested field, [#4005](https://github.com/pydantic/pydantic/issues/4005) by [@sergiosim](https://github.com/sergiosim) +* Add JSON-compatible float constraint `allow_inf_nan`, [#3994](https://github.com/pydantic/pydantic/issues/3994) by [@tiangolo](https://github.com/tiangolo) +* Remove undefined behaviour when `env_prefix` had characters in common with `env_nested_delimiter`, [#3975](https://github.com/pydantic/pydantic/issues/3975) by [@arsenron](https://github.com/arsenron) +* Support generics model with `create_model`, [#3945](https://github.com/pydantic/pydantic/issues/3945) by [@hot123s](https://github.com/hot123s) +* allow submodels to overwrite extra field info, [#3934](https://github.com/pydantic/pydantic/issues/3934) by [@PrettyWood](https://github.com/PrettyWood) +* Document and test structural pattern matching ([PEP 636](https://peps.python.org/pep-0636/)) on `BaseModel`, [#3920](https://github.com/pydantic/pydantic/issues/3920) by [@irgolic](https://github.com/irgolic) +* Fix incorrect deserialization of python timedelta object to ISO 8601 for negative time deltas. + Minus was serialized in incorrect place ("P-1DT23H59M59.888735S" instead of correct "-P1DT23H59M59.888735S"), [#3899](https://github.com/pydantic/pydantic/issues/3899) by [@07pepa](https://github.com/07pepa) +* Fix validation of discriminated union fields with an alias when passing a model instance, [#3846](https://github.com/pydantic/pydantic/issues/3846) by [@chornsby](https://github.com/chornsby) +* Add a CockroachDsn type to validate CockroachDB connection strings. The type + supports the following schemes: `cockroachdb`, `cockroachdb+psycopg2` and `cockroachdb+asyncpg`, [#3839](https://github.com/pydantic/pydantic/issues/3839) by [@blubber](https://github.com/blubber) +* Fix MyPy plugin to not override pre-existing `__init__` method in models, [#3824](https://github.com/pydantic/pydantic/issues/3824) by [@patrick91](https://github.com/patrick91) +* Fix mypy version checking, [#3783](https://github.com/pydantic/pydantic/issues/3783) by [@KotlinIsland](https://github.com/KotlinIsland) +* support overwriting dunder attributes of `BaseModel` instances, [#3777](https://github.com/pydantic/pydantic/issues/3777) by [@PrettyWood](https://github.com/PrettyWood) +* Added `ConstrainedDate` and `condate`, [#3740](https://github.com/pydantic/pydantic/issues/3740) by [@hottwaj](https://github.com/hottwaj) +* Support `kw_only` in dataclasses, [#3670](https://github.com/pydantic/pydantic/issues/3670) by [@detachhead](https://github.com/detachhead) +* Add comparison method for `Color` class, [#3646](https://github.com/pydantic/pydantic/issues/3646) by [@aminalaee](https://github.com/aminalaee) +* Drop support for python3.6, associated cleanup, [#3605](https://github.com/pydantic/pydantic/issues/3605) by [@samuelcolvin](https://github.com/samuelcolvin) +* created new function `to_lower_camel()` for "non pascal case" camel case, [#3463](https://github.com/pydantic/pydantic/issues/3463) by [@schlerp](https://github.com/schlerp) +* Add checks to `default` and `default_factory` arguments in Mypy plugin, [#3430](https://github.com/pydantic/pydantic/issues/3430) by [@klaa97](https://github.com/klaa97) +* fix mangling of `inspect.signature` for `BaseModel`, [#3413](https://github.com/pydantic/pydantic/issues/3413) by [@fix-inspect-signature](https://github.com/fix-inspect-signature) +* Adds the `SecretField` abstract class so that all the current and future secret fields like `SecretStr` and `SecretBytes` will derive from it, [#3409](https://github.com/pydantic/pydantic/issues/3409) by [@expobrain](https://github.com/expobrain) +* Support multi hosts validation in `PostgresDsn`, [#3337](https://github.com/pydantic/pydantic/issues/3337) by [@rglsk](https://github.com/rglsk) +* Fix parsing of very small numeric timedelta values, [#3315](https://github.com/pydantic/pydantic/issues/3315) by [@samuelcolvin](https://github.com/samuelcolvin) +* Update `SecretsSettingsSource` to respect `config.case_sensitive`, [#3273](https://github.com/pydantic/pydantic/issues/3273) by [@JeanArhancet](https://github.com/JeanArhancet) +* Add MongoDB network data source name (DSN) schema, [#3229](https://github.com/pydantic/pydantic/issues/3229) by [@snosratiershad](https://github.com/snosratiershad) +* Add support for multiple dotenv files, [#3222](https://github.com/pydantic/pydantic/issues/3222) by [@rekyungmin](https://github.com/rekyungmin) +* Raise an explicit `ConfigError` when multiple fields are incorrectly set for a single validator, [#3215](https://github.com/pydantic/pydantic/issues/3215) by [@SunsetOrange](https://github.com/SunsetOrange) +* Allow ellipsis on `Field`s inside `Annotated` for `TypedDicts` required, [#3133](https://github.com/pydantic/pydantic/issues/3133) by [@ezegomez](https://github.com/ezegomez) +* Catch overflow errors in `int_validator`, [#3112](https://github.com/pydantic/pydantic/issues/3112) by [@ojii](https://github.com/ojii) +* Adds a `__rich_repr__` method to `Representation` class which enables pretty printing with [Rich](https://github.com/willmcgugan/rich), [#3099](https://github.com/pydantic/pydantic/issues/3099) by [@willmcgugan](https://github.com/willmcgugan) +* Add percent encoding in `AnyUrl` and descendent types, [#3061](https://github.com/pydantic/pydantic/issues/3061) by [@FaresAhmedb](https://github.com/FaresAhmedb) +* `validate_arguments` decorator now supports `alias`, [#3019](https://github.com/pydantic/pydantic/issues/3019) by [@MAD-py](https://github.com/MAD-py) +* Avoid `__dict__` and `__weakref__` attributes in `AnyUrl` and IP address fields, [#2890](https://github.com/pydantic/pydantic/issues/2890) by [@nuno-andre](https://github.com/nuno-andre) +* Add ability to use `Final` in a field type annotation, [#2766](https://github.com/pydantic/pydantic/issues/2766) by [@uriyyo](https://github.com/uriyyo) +* Update requirement to `typing_extensions>=4.1.0` to guarantee `dataclass_transform` is available, [#4424](https://github.com/pydantic/pydantic/issues/4424) by [@commonism](https://github.com/commonism) +* Add Explosion and AWS to main sponsors, [#4413](https://github.com/pydantic/pydantic/issues/4413) by [@samuelcolvin](https://github.com/samuelcolvin) +* Update documentation for `copy_on_model_validation` to reflect recent changes, [#4369](https://github.com/pydantic/pydantic/issues/4369) by [@samuelcolvin](https://github.com/samuelcolvin) +* Runtime warning if `__slots__` is passed to `create_model`, `__slots__` is then ignored, [#4432](https://github.com/pydantic/pydantic/issues/4432) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add type hints to `BaseSettings.Config` to avoid mypy errors, also correct mypy version compatibility notice in docs, [#4450](https://github.com/pydantic/pydantic/issues/4450) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.10.0b1 (2022-08-24) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0b1) for details. + +## v1.10.0a2 (2022-08-24) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0a2) for details. + +## v1.10.0a1 (2022-08-22) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0a1) for details. + +## v1.9.2 (2022-08-11) + +**Revert Breaking Change**: _v1.9.1_ introduced a breaking change where model fields were +deep copied by default, this release reverts the default behaviour to match _v1.9.0_ and before, +while also allow deep-copy behaviour via `copy_on_model_validation = 'deep'`. See [#4092](https://github.com/pydantic/pydantic/issues/4092) for more information. + +* Allow for shallow copies of model fields, `Config.copy_on_model_validation` is now a str which must be + `'none'`, `'deep'`, or `'shallow'` corresponding to not copying, deep copy & shallow copy; default `'shallow'`, + [#4093](https://github.com/pydantic/pydantic/issues/4093) by [@timkpaine](https://github.com/timkpaine) + +## v1.9.1 (2022-05-19) + +Thank you to pydantic's sponsors: +@tiangolo, [@stellargraph](https://github.com/stellargraph), [@JonasKs](https://github.com/JonasKs), [@grillazz](https://github.com/grillazz), [@Mazyod](https://github.com/Mazyod), [@kevinalh](https://github.com/kevinalh), [@chdsbd](https://github.com/chdsbd), [@povilasb](https://github.com/povilasb), [@povilasb](https://github.com/povilasb), [@jina-ai](https://github.com/jina-ai), +@mainframeindustries, [@robusta-dev](https://github.com/robusta-dev), [@SendCloud](https://github.com/SendCloud), [@rszamszur](https://github.com/rszamszur), [@jodal](https://github.com/jodal), [@hardbyte](https://github.com/hardbyte), [@corleyma](https://github.com/corleyma), [@daddycocoaman](https://github.com/daddycocoaman), +@Rehket, [@jokull](https://github.com/jokull), [@reillysiemens](https://github.com/reillysiemens), [@westonsteimel](https://github.com/westonsteimel), [@primer-io](https://github.com/primer-io), [@koxudaxi](https://github.com/koxudaxi), [@browniebroke](https://github.com/browniebroke), [@stradivari96](https://github.com/stradivari96), +@adriangb, [@kamalgill](https://github.com/kamalgill), [@jqueguiner](https://github.com/jqueguiner), [@dev-zero](https://github.com/dev-zero), [@datarootsio](https://github.com/datarootsio), [@RedCarpetUp](https://github.com/RedCarpetUp) +for their kind support. + +* Limit the size of `generics._generic_types_cache` and `generics._assigned_parameters` + to avoid unlimited increase in memory usage, [#4083](https://github.com/pydantic/pydantic/issues/4083) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add Jupyverse and FPS as Jupyter projects using pydantic, [#4082](https://github.com/pydantic/pydantic/issues/4082) by [@davidbrochart](https://github.com/davidbrochart) +* Speedup `__isinstancecheck__` on pydantic models when the type is not a model, may also avoid memory "leaks", [#4081](https://github.com/pydantic/pydantic/issues/4081) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix in-place modification of `FieldInfo` that caused problems with PEP 593 type aliases, [#4067](https://github.com/pydantic/pydantic/issues/4067) by [@adriangb](https://github.com/adriangb) +* Add support for autocomplete in VS Code via `__dataclass_transform__` when using `pydantic.dataclasses.dataclass`, [#4006](https://github.com/pydantic/pydantic/issues/4006) by [@giuliano-oliveira](https://github.com/giuliano-oliveira) +* Remove benchmarks from codebase and docs, [#3973](https://github.com/pydantic/pydantic/issues/3973) by [@samuelcolvin](https://github.com/samuelcolvin) +* Typing checking with pyright in CI, improve docs on vscode/pylance/pyright, [#3972](https://github.com/pydantic/pydantic/issues/3972) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix nested Python dataclass schema regression, [#3819](https://github.com/pydantic/pydantic/issues/3819) by [@himbeles](https://github.com/himbeles) +* Update documentation about lazy evaluation of sources for Settings, [#3806](https://github.com/pydantic/pydantic/issues/3806) by [@garyd203](https://github.com/garyd203) +* Prevent subclasses of bytes being converted to bytes, [#3706](https://github.com/pydantic/pydantic/issues/3706) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fixed "error checking inheritance of" when using PEP585 and PEP604 type hints, [#3681](https://github.com/pydantic/pydantic/issues/3681) by [@aleksul](https://github.com/aleksul) +* Allow self referencing `ClassVar`s in models, [#3679](https://github.com/pydantic/pydantic/issues/3679) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change, see [#4106](https://github.com/pydantic/pydantic/issues/4106)**: Fix issue with self-referencing dataclass, [#3675](https://github.com/pydantic/pydantic/issues/3675) by [@uriyyo](https://github.com/uriyyo) +* Include non-standard port numbers in rendered URLs, [#3652](https://github.com/pydantic/pydantic/issues/3652) by [@dolfinus](https://github.com/dolfinus) +* `Config.copy_on_model_validation` does a deep copy and not a shallow one, [#3641](https://github.com/pydantic/pydantic/issues/3641) by [@PrettyWood](https://github.com/PrettyWood) +* fix: clarify that discriminated unions do not support singletons, [#3636](https://github.com/pydantic/pydantic/issues/3636) by [@tommilligan](https://github.com/tommilligan) +* Add `read_text(encoding='utf-8')` for `setup.py`, [#3625](https://github.com/pydantic/pydantic/issues/3625) by [@hswong3i](https://github.com/hswong3i) +* Fix JSON Schema generation for Discriminated Unions within lists, [#3608](https://github.com/pydantic/pydantic/issues/3608) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.9.0 (2021-12-31) + +Thank you to pydantic's sponsors: +@sthagen, [@timdrijvers](https://github.com/timdrijvers), [@toinbis](https://github.com/toinbis), [@koxudaxi](https://github.com/koxudaxi), [@ginomempin](https://github.com/ginomempin), [@primer-io](https://github.com/primer-io), [@and-semakin](https://github.com/and-semakin), [@westonsteimel](https://github.com/westonsteimel), [@reillysiemens](https://github.com/reillysiemens), +@es3n1n, [@jokull](https://github.com/jokull), [@JonasKs](https://github.com/JonasKs), [@Rehket](https://github.com/Rehket), [@corleyma](https://github.com/corleyma), [@daddycocoaman](https://github.com/daddycocoaman), [@hardbyte](https://github.com/hardbyte), [@datarootsio](https://github.com/datarootsio), [@jodal](https://github.com/jodal), [@aminalaee](https://github.com/aminalaee), [@rafsaf](https://github.com/rafsaf), +@jqueguiner, [@chdsbd](https://github.com/chdsbd), [@kevinalh](https://github.com/kevinalh), [@Mazyod](https://github.com/Mazyod), [@grillazz](https://github.com/grillazz), [@JonasKs](https://github.com/JonasKs), [@simw](https://github.com/simw), [@leynier](https://github.com/leynier), [@xfenix](https://github.com/xfenix) +for their kind support. + +### Highlights + +* add Python 3.10 support, [#2885](https://github.com/pydantic/pydantic/issues/2885) by [@PrettyWood](https://github.com/PrettyWood) +* [Discriminated unions](https://pydantic-docs.helpmanual.io/usage/types/#discriminated-unions-aka-tagged-unions), [#619](https://github.com/pydantic/pydantic/issues/619) by [@PrettyWood](https://github.com/PrettyWood) +* [`Config.smart_union` for better union logic](https://pydantic-docs.helpmanual.io/usage/model_config/#smart-union), [#2092](https://github.com/pydantic/pydantic/issues/2092) by [@PrettyWood](https://github.com/PrettyWood) +* Binaries for Macos M1 CPUs, [#3498](https://github.com/pydantic/pydantic/issues/3498) by [@samuelcolvin](https://github.com/samuelcolvin) +* Complex types can be set via [nested environment variables](https://pydantic-docs.helpmanual.io/usage/settings/#parsing-environment-variable-values), e.g. `foo___bar`, [#3159](https://github.com/pydantic/pydantic/issues/3159) by [@Air-Mark](https://github.com/Air-Mark) +* add a dark mode to _pydantic_ documentation, [#2913](https://github.com/pydantic/pydantic/issues/2913) by [@gbdlin](https://github.com/gbdlin) +* Add support for autocomplete in VS Code via `__dataclass_transform__`, [#2721](https://github.com/pydantic/pydantic/issues/2721) by [@tiangolo](https://github.com/tiangolo) +* Add "exclude" as a field parameter so that it can be configured using model config, [#660](https://github.com/pydantic/pydantic/issues/660) by [@daviskirk](https://github.com/daviskirk) + +### v1.9.0 (2021-12-31) Changes + +* Apply `update_forward_refs` to `Config.json_encodes` prevent name clashes in types defined via strings, [#3583](https://github.com/pydantic/pydantic/issues/3583) by [@samuelcolvin](https://github.com/samuelcolvin) +* Extend pydantic's mypy plugin to support mypy versions `0.910`, `0.920`, `0.921` & `0.930`, [#3573](https://github.com/pydantic/pydantic/issues/3573) & [#3594](https://github.com/pydantic/pydantic/issues/3594) by [@PrettyWood](https://github.com/PrettyWood), [@christianbundy](https://github.com/christianbundy), [@samuelcolvin](https://github.com/samuelcolvin) + +### v1.9.0a2 (2021-12-24) Changes + +* support generic models with discriminated union, [#3551](https://github.com/pydantic/pydantic/issues/3551) by [@PrettyWood](https://github.com/PrettyWood) +* keep old behaviour of `json()` by default, [#3542](https://github.com/pydantic/pydantic/issues/3542) by [@PrettyWood](https://github.com/PrettyWood) +* Removed typing-only `__root__` attribute from `BaseModel`, [#3540](https://github.com/pydantic/pydantic/issues/3540) by [@layday](https://github.com/layday) +* Build Python 3.10 wheels, [#3539](https://github.com/pydantic/pydantic/issues/3539) by [@mbachry](https://github.com/mbachry) +* Fix display of `extra` fields with model `__repr__`, [#3234](https://github.com/pydantic/pydantic/issues/3234) by [@cocolman](https://github.com/cocolman) +* models copied via `Config.copy_on_model_validation` always have all fields, [#3201](https://github.com/pydantic/pydantic/issues/3201) by [@PrettyWood](https://github.com/PrettyWood) +* nested ORM from nested dictionaries, [#3182](https://github.com/pydantic/pydantic/issues/3182) by [@PrettyWood](https://github.com/PrettyWood) +* fix link to discriminated union section by [@PrettyWood](https://github.com/PrettyWood) + +### v1.9.0a1 (2021-12-18) Changes + +* Add support for `Decimal`-specific validation configurations in `Field()`, additionally to using `condecimal()`, + to allow better support from editors and tooling, [#3507](https://github.com/pydantic/pydantic/issues/3507) by [@tiangolo](https://github.com/tiangolo) +* Add `arm64` binaries suitable for MacOS with an M1 CPU to PyPI, [#3498](https://github.com/pydantic/pydantic/issues/3498) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix issue where `None` was considered invalid when using a `Union` type containing `Any` or `object`, [#3444](https://github.com/pydantic/pydantic/issues/3444) by [@tharradine](https://github.com/tharradine) +* When generating field schema, pass optional `field` argument (of type + `pydantic.fields.ModelField`) to `__modify_schema__()` if present, [#3434](https://github.com/pydantic/pydantic/issues/3434) by [@jasujm](https://github.com/jasujm) +* Fix issue when pydantic fail to parse `typing.ClassVar` string type annotation, [#3401](https://github.com/pydantic/pydantic/issues/3401) by [@uriyyo](https://github.com/uriyyo) +* Mention Python >= 3.9.2 as an alternative to `typing_extensions.TypedDict`, [#3374](https://github.com/pydantic/pydantic/issues/3374) by [@BvB93](https://github.com/BvB93) +* Changed the validator method name in the [Custom Errors example](https://pydantic-docs.helpmanual.io/usage/models/#custom-errors) + to more accurately describe what the validator is doing; changed from `name_must_contain_space` to ` value_must_equal_bar`, [#3327](https://github.com/pydantic/pydantic/issues/3327) by [@michaelrios28](https://github.com/michaelrios28) +* Add `AmqpDsn` class, [#3254](https://github.com/pydantic/pydantic/issues/3254) by [@kludex](https://github.com/kludex) +* Always use `Enum` value as default in generated JSON schema, [#3190](https://github.com/pydantic/pydantic/issues/3190) by [@joaommartins](https://github.com/joaommartins) +* Add support for Mypy 0.920, [#3175](https://github.com/pydantic/pydantic/issues/3175) by [@christianbundy](https://github.com/christianbundy) +* `validate_arguments` now supports `extra` customization (used to always be `Extra.forbid`), [#3161](https://github.com/pydantic/pydantic/issues/3161) by [@PrettyWood](https://github.com/PrettyWood) +* Complex types can be set by nested environment variables, [#3159](https://github.com/pydantic/pydantic/issues/3159) by [@Air-Mark](https://github.com/Air-Mark) +* Fix mypy plugin to collect fields based on `pydantic.utils.is_valid_field` so that it ignores untyped private variables, [#3146](https://github.com/pydantic/pydantic/issues/3146) by [@hi-ogawa](https://github.com/hi-ogawa) +* fix `validate_arguments` issue with `Config.validate_all`, [#3135](https://github.com/pydantic/pydantic/issues/3135) by [@PrettyWood](https://github.com/PrettyWood) +* avoid dict coercion when using dict subclasses as field type, [#3122](https://github.com/pydantic/pydantic/issues/3122) by [@PrettyWood](https://github.com/PrettyWood) +* add support for `object` type, [#3062](https://github.com/pydantic/pydantic/issues/3062) by [@PrettyWood](https://github.com/PrettyWood) +* Updates pydantic dataclasses to keep `_special` properties on parent classes, [#3043](https://github.com/pydantic/pydantic/issues/3043) by [@zulrang](https://github.com/zulrang) +* Add a `TypedDict` class for error objects, [#3038](https://github.com/pydantic/pydantic/issues/3038) by [@matthewhughes934](https://github.com/matthewhughes934) +* Fix support for using a subclass of an annotation as a default, [#3018](https://github.com/pydantic/pydantic/issues/3018) by [@JacobHayes](https://github.com/JacobHayes) +* make `create_model_from_typeddict` mypy compliant, [#3008](https://github.com/pydantic/pydantic/issues/3008) by [@PrettyWood](https://github.com/PrettyWood) +* Make multiple inheritance work when using `PrivateAttr`, [#2989](https://github.com/pydantic/pydantic/issues/2989) by [@hmvp](https://github.com/hmvp) +* Parse environment variables as JSON, if they have a `Union` type with a complex subfield, [#2936](https://github.com/pydantic/pydantic/issues/2936) by [@cbartz](https://github.com/cbartz) +* Prevent `StrictStr` permitting `Enum` values where the enum inherits from `str`, [#2929](https://github.com/pydantic/pydantic/issues/2929) by [@samuelcolvin](https://github.com/samuelcolvin) +* Make `SecretsSettingsSource` parse values being assigned to fields of complex types when sourced from a secrets file, + just as when sourced from environment variables, [#2917](https://github.com/pydantic/pydantic/issues/2917) by [@davidmreed](https://github.com/davidmreed) +* add a dark mode to _pydantic_ documentation, [#2913](https://github.com/pydantic/pydantic/issues/2913) by [@gbdlin](https://github.com/gbdlin) +* Make `pydantic-mypy` plugin compatible with `pyproject.toml` configuration, consistent with `mypy` changes. + See the [doc](https://pydantic-docs.helpmanual.io/mypy_plugin/#configuring-the-plugin) for more information, [#2908](https://github.com/pydantic/pydantic/issues/2908) by [@jrwalk](https://github.com/jrwalk) +* add Python 3.10 support, [#2885](https://github.com/pydantic/pydantic/issues/2885) by [@PrettyWood](https://github.com/PrettyWood) +* Correctly parse generic models with `Json[T]`, [#2860](https://github.com/pydantic/pydantic/issues/2860) by [@geekingfrog](https://github.com/geekingfrog) +* Update contrib docs re: Python version to use for building docs, [#2856](https://github.com/pydantic/pydantic/issues/2856) by [@paxcodes](https://github.com/paxcodes) +* Clarify documentation about _pydantic_'s support for custom validation and strict type checking, + despite _pydantic_ being primarily a parsing library, [#2855](https://github.com/pydantic/pydantic/issues/2855) by [@paxcodes](https://github.com/paxcodes) +* Fix schema generation for `Deque` fields, [#2810](https://github.com/pydantic/pydantic/issues/2810) by [@sergejkozin](https://github.com/sergejkozin) +* fix an edge case when mixing constraints and `Literal`, [#2794](https://github.com/pydantic/pydantic/issues/2794) by [@PrettyWood](https://github.com/PrettyWood) +* Fix postponed annotation resolution for `NamedTuple` and `TypedDict` when they're used directly as the type of fields + within Pydantic models, [#2760](https://github.com/pydantic/pydantic/issues/2760) by [@jameysharp](https://github.com/jameysharp) +* Fix bug when `mypy` plugin fails on `construct` method call for `BaseSettings` derived classes, [#2753](https://github.com/pydantic/pydantic/issues/2753) by [@uriyyo](https://github.com/uriyyo) +* Add function overloading for a `pydantic.create_model` function, [#2748](https://github.com/pydantic/pydantic/issues/2748) by [@uriyyo](https://github.com/uriyyo) +* Fix mypy plugin issue with self field declaration, [#2743](https://github.com/pydantic/pydantic/issues/2743) by [@uriyyo](https://github.com/uriyyo) +* The colon at the end of the line "The fields which were supplied when user was initialised:" suggests that the code following it is related. + Changed it to a period, [#2733](https://github.com/pydantic/pydantic/issues/2733) by [@krisaoe](https://github.com/krisaoe) +* Renamed variable `schema` to `schema_` to avoid shadowing of global variable name, [#2724](https://github.com/pydantic/pydantic/issues/2724) by [@shahriyarr](https://github.com/shahriyarr) +* Add support for autocomplete in VS Code via `__dataclass_transform__`, [#2721](https://github.com/pydantic/pydantic/issues/2721) by [@tiangolo](https://github.com/tiangolo) +* add missing type annotations in `BaseConfig` and handle `max_length = 0`, [#2719](https://github.com/pydantic/pydantic/issues/2719) by [@PrettyWood](https://github.com/PrettyWood) +* Change `orm_mode` checking to allow recursive ORM mode parsing with dicts, [#2718](https://github.com/pydantic/pydantic/issues/2718) by [@nuno-andre](https://github.com/nuno-andre) +* Add episode 313 of the *Talk Python To Me* podcast, where Michael Kennedy and Samuel Colvin discuss *pydantic*, to the docs, [#2712](https://github.com/pydantic/pydantic/issues/2712) by [@RatulMaharaj](https://github.com/RatulMaharaj) +* fix JSON schema generation when a field is of type `NamedTuple` and has a default value, [#2707](https://github.com/pydantic/pydantic/issues/2707) by [@PrettyWood](https://github.com/PrettyWood) +* `Enum` fields now properly support extra kwargs in schema generation, [#2697](https://github.com/pydantic/pydantic/issues/2697) by [@sammchardy](https://github.com/sammchardy) +* **Breaking Change, see [#3780](https://github.com/pydantic/pydantic/issues/3780)**: Make serialization of referenced pydantic models possible, [#2650](https://github.com/pydantic/pydantic/issues/2650) by [@PrettyWood](https://github.com/PrettyWood) +* Add `uniqueItems` option to `ConstrainedList`, [#2618](https://github.com/pydantic/pydantic/issues/2618) by [@nuno-andre](https://github.com/nuno-andre) +* Try to evaluate forward refs automatically at model creation, [#2588](https://github.com/pydantic/pydantic/issues/2588) by [@uriyyo](https://github.com/uriyyo) +* Switch docs preview and coverage display to use [smokeshow](https://smokeshow.helpmanual.io/), [#2580](https://github.com/pydantic/pydantic/issues/2580) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `__version__` attribute to pydantic module, [#2572](https://github.com/pydantic/pydantic/issues/2572) by [@paxcodes](https://github.com/paxcodes) +* Add `postgresql+asyncpg`, `postgresql+pg8000`, `postgresql+psycopg2`, `postgresql+psycopg2cffi`, `postgresql+py-postgresql` + and `postgresql+pygresql` schemes for `PostgresDsn`, [#2567](https://github.com/pydantic/pydantic/issues/2567) by [@postgres-asyncpg](https://github.com/postgres-asyncpg) +* Enable the Hypothesis plugin to generate a constrained decimal when the `decimal_places` argument is specified, [#2524](https://github.com/pydantic/pydantic/issues/2524) by [@cwe5590](https://github.com/cwe5590) +* Allow `collections.abc.Callable` to be used as type in Python 3.9, [#2519](https://github.com/pydantic/pydantic/issues/2519) by [@daviskirk](https://github.com/daviskirk) +* Documentation update how to custom compile pydantic when using pip install, small change in `setup.py` + to allow for custom CFLAGS when compiling, [#2517](https://github.com/pydantic/pydantic/issues/2517) by [@peterroelants](https://github.com/peterroelants) +* remove side effect of `default_factory` to run it only once even if `Config.validate_all` is set, [#2515](https://github.com/pydantic/pydantic/issues/2515) by [@PrettyWood](https://github.com/PrettyWood) +* Add lookahead to ip regexes for `AnyUrl` hosts. This allows urls with DNS labels + looking like IPs to validate as they are perfectly valid host names, [#2512](https://github.com/pydantic/pydantic/issues/2512) by [@sbv-csis](https://github.com/sbv-csis) +* Set `minItems` and `maxItems` in generated JSON schema for fixed-length tuples, [#2497](https://github.com/pydantic/pydantic/issues/2497) by [@PrettyWood](https://github.com/PrettyWood) +* Add `strict` argument to `conbytes`, [#2489](https://github.com/pydantic/pydantic/issues/2489) by [@koxudaxi](https://github.com/koxudaxi) +* Support user defined generic field types in generic models, [#2465](https://github.com/pydantic/pydantic/issues/2465) by [@daviskirk](https://github.com/daviskirk) +* Add an example and a short explanation of subclassing `GetterDict` to docs, [#2463](https://github.com/pydantic/pydantic/issues/2463) by [@nuno-andre](https://github.com/nuno-andre) +* add `KafkaDsn` type, `HttpUrl` now has default port 80 for http and 443 for https, [#2447](https://github.com/pydantic/pydantic/issues/2447) by [@MihanixA](https://github.com/MihanixA) +* Add `PastDate` and `FutureDate` types, [#2425](https://github.com/pydantic/pydantic/issues/2425) by [@Kludex](https://github.com/Kludex) +* Support generating schema for `Generic` fields with subtypes, [#2375](https://github.com/pydantic/pydantic/issues/2375) by [@maximberg](https://github.com/maximberg) +* fix(encoder): serialize `NameEmail` to str, [#2341](https://github.com/pydantic/pydantic/issues/2341) by [@alecgerona](https://github.com/alecgerona) +* add `Config.smart_union` to prevent coercion in `Union` if possible, see + [the doc](https://pydantic-docs.helpmanual.io/usage/model_config/#smart-union) for more information, [#2092](https://github.com/pydantic/pydantic/issues/2092) by [@PrettyWood](https://github.com/PrettyWood) +* Add ability to use `typing.Counter` as a model field type, [#2060](https://github.com/pydantic/pydantic/issues/2060) by [@uriyyo](https://github.com/uriyyo) +* Add parameterised subclasses to `__bases__` when constructing new parameterised classes, so that `A <: B => A[int] <: B[int]`, [#2007](https://github.com/pydantic/pydantic/issues/2007) by [@diabolo-dan](https://github.com/diabolo-dan) +* Create `FileUrl` type that allows URLs that conform to [RFC 8089](https://tools.ietf.org/html/rfc8089#section-2). + Add `host_required` parameter, which is `True` by default (`AnyUrl` and subclasses), `False` in `RedisDsn`, `FileUrl`, [#1983](https://github.com/pydantic/pydantic/issues/1983) by [@vgerak](https://github.com/vgerak) +* add `confrozenset()`, analogous to `conset()` and `conlist()`, [#1897](https://github.com/pydantic/pydantic/issues/1897) by [@PrettyWood](https://github.com/PrettyWood) +* stop calling parent class `root_validator` if overridden, [#1895](https://github.com/pydantic/pydantic/issues/1895) by [@PrettyWood](https://github.com/PrettyWood) +* Add `repr` (defaults to `True`) parameter to `Field`, to hide it from the default representation of the `BaseModel`, [#1831](https://github.com/pydantic/pydantic/issues/1831) by [@fnep](https://github.com/fnep) +* Accept empty query/fragment URL parts, [#1807](https://github.com/pydantic/pydantic/issues/1807) by [@xavier](https://github.com/xavier) + +## v1.8.2 (2021-05-11) + +!!! warning + A security vulnerability, level "moderate" is fixed in v1.8.2. Please upgrade **ASAP**. + See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) + +* **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` + (or their negative values) does not cause an infinite loop, + see security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) +* fix schema generation with Enum by generating a valid name, [#2575](https://github.com/pydantic/pydantic/issues/2575) by [@PrettyWood](https://github.com/PrettyWood) +* fix JSON schema generation with a `Literal` of an enum member, [#2536](https://github.com/pydantic/pydantic/issues/2536) by [@PrettyWood](https://github.com/PrettyWood) +* Fix bug with configurations declarations that are passed as + keyword arguments during class creation, [#2532](https://github.com/pydantic/pydantic/issues/2532) by [@uriyyo](https://github.com/uriyyo) +* Allow passing `json_encoders` in class kwargs, [#2521](https://github.com/pydantic/pydantic/issues/2521) by [@layday](https://github.com/layday) +* support arbitrary types with custom `__eq__`, [#2483](https://github.com/pydantic/pydantic/issues/2483) by [@PrettyWood](https://github.com/PrettyWood) +* support `Annotated` in `validate_arguments` and in generic models with Python 3.9, [#2483](https://github.com/pydantic/pydantic/issues/2483) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.8.1 (2021-03-03) + +Bug fixes for regressions and new features from `v1.8` + +* allow elements of `Config.field` to update elements of a `Field`, [#2461](https://github.com/pydantic/pydantic/issues/2461) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix validation with a `BaseModel` field and a custom root type, [#2449](https://github.com/pydantic/pydantic/issues/2449) by [@PrettyWood](https://github.com/PrettyWood) +* expose `Pattern` encoder to `fastapi`, [#2444](https://github.com/pydantic/pydantic/issues/2444) by [@PrettyWood](https://github.com/PrettyWood) +* enable the Hypothesis plugin to generate a constrained float when the `multiple_of` argument is specified, [#2442](https://github.com/pydantic/pydantic/issues/2442) by [@tobi-lipede-oodle](https://github.com/tobi-lipede-oodle) +* Avoid `RecursionError` when using some types like `Enum` or `Literal` with generic models, [#2436](https://github.com/pydantic/pydantic/issues/2436) by [@PrettyWood](https://github.com/PrettyWood) +* do not overwrite declared `__hash__` in subclasses of a model, [#2422](https://github.com/pydantic/pydantic/issues/2422) by [@PrettyWood](https://github.com/PrettyWood) +* fix `mypy` complaints on `Path` and `UUID` related custom types, [#2418](https://github.com/pydantic/pydantic/issues/2418) by [@PrettyWood](https://github.com/PrettyWood) +* Support properly variable length tuples of compound types, [#2416](https://github.com/pydantic/pydantic/issues/2416) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.8 (2021-02-26) + +Thank you to pydantic's sponsors: +@jorgecarleitao, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@koxudaxi](https://github.com/koxudaxi), [@timdrijvers](https://github.com/timdrijvers), [@mkeen](https://github.com/mkeen), [@meadsteve](https://github.com/meadsteve), +@ginomempin, [@primer-io](https://github.com/primer-io), [@and-semakin](https://github.com/and-semakin), [@tomthorogood](https://github.com/tomthorogood), [@AjitZK](https://github.com/AjitZK), [@westonsteimel](https://github.com/westonsteimel), [@Mazyod](https://github.com/Mazyod), [@christippett](https://github.com/christippett), [@CarlosDomingues](https://github.com/CarlosDomingues), +@Kludex, [@r-m-n](https://github.com/r-m-n) +for their kind support. + +### Highlights + +* [Hypothesis plugin](https://pydantic-docs.helpmanual.io/hypothesis_plugin/) for testing, [#2097](https://github.com/pydantic/pydantic/issues/2097) by [@Zac-HD](https://github.com/Zac-HD) +* support for [`NamedTuple` and `TypedDict`](https://pydantic-docs.helpmanual.io/usage/types/#annotated-types), [#2216](https://github.com/pydantic/pydantic/issues/2216) by [@PrettyWood](https://github.com/PrettyWood) +* Support [`Annotated` hints on model fields](https://pydantic-docs.helpmanual.io/usage/schema/#typingannotated-fields), [#2147](https://github.com/pydantic/pydantic/issues/2147) by [@JacobHayes](https://github.com/JacobHayes) +* [`frozen` parameter on `Config`](https://pydantic-docs.helpmanual.io/usage/model_config/) to allow models to be hashed, [#1880](https://github.com/pydantic/pydantic/issues/1880) by [@rhuille](https://github.com/rhuille) + +### Changes + +* **Breaking Change**, remove old deprecation aliases from v1, [#2415](https://github.com/pydantic/pydantic/issues/2415) by [@samuelcolvin](https://github.com/samuelcolvin): + * remove notes on migrating to v1 in docs + * remove `Schema` which was replaced by `Field` + * remove `Config.case_insensitive` which was replaced by `Config.case_sensitive` (default `False`) + * remove `Config.allow_population_by_alias` which was replaced by `Config.allow_population_by_field_name` + * remove `model.fields` which was replaced by `model.__fields__` + * remove `model.to_string()` which was replaced by `str(model)` + * remove `model.__values__` which was replaced by `model.__dict__` +* **Breaking Change:** always validate only first sublevel items with `each_item`. + There were indeed some edge cases with some compound types where the validated items were the last sublevel ones, [#1933](https://github.com/pydantic/pydantic/issues/1933) by [@PrettyWood](https://github.com/PrettyWood) +* Update docs extensions to fix local syntax highlighting, [#2400](https://github.com/pydantic/pydantic/issues/2400) by [@daviskirk](https://github.com/daviskirk) +* fix: allow `utils.lenient_issubclass` to handle `typing.GenericAlias` objects like `list[str]` in Python >= 3.9, [#2399](https://github.com/pydantic/pydantic/issues/2399) by [@daviskirk](https://github.com/daviskirk) +* Improve field declaration for _pydantic_ `dataclass` by allowing the usage of _pydantic_ `Field` or `'metadata'` kwarg of `dataclasses.field`, [#2384](https://github.com/pydantic/pydantic/issues/2384) by [@PrettyWood](https://github.com/PrettyWood) +* Making `typing-extensions` a required dependency, [#2368](https://github.com/pydantic/pydantic/issues/2368) by [@samuelcolvin](https://github.com/samuelcolvin) +* Make `resolve_annotations` more lenient, allowing for missing modules, [#2363](https://github.com/pydantic/pydantic/issues/2363) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allow configuring models through class kwargs, [#2356](https://github.com/pydantic/pydantic/issues/2356) by [@Bobronium](https://github.com/Bobronium) +* Prevent `Mapping` subclasses from always being coerced to `dict`, [#2325](https://github.com/pydantic/pydantic/issues/2325) by [@ofek](https://github.com/ofek) +* fix: allow `None` for type `Optional[conset / conlist]`, [#2320](https://github.com/pydantic/pydantic/issues/2320) by [@PrettyWood](https://github.com/PrettyWood) +* Support empty tuple type, [#2318](https://github.com/pydantic/pydantic/issues/2318) by [@PrettyWood](https://github.com/PrettyWood) +* fix: `python_requires` metadata to require >=3.6.1, [#2306](https://github.com/pydantic/pydantic/issues/2306) by [@hukkinj1](https://github.com/hukkinj1) +* Properly encode `Decimal` with, or without any decimal places, [#2293](https://github.com/pydantic/pydantic/issues/2293) by [@hultner](https://github.com/hultner) +* fix: update `__fields_set__` in `BaseModel.copy(update=…)`, [#2290](https://github.com/pydantic/pydantic/issues/2290) by [@PrettyWood](https://github.com/PrettyWood) +* fix: keep order of fields with `BaseModel.construct()`, [#2281](https://github.com/pydantic/pydantic/issues/2281) by [@PrettyWood](https://github.com/PrettyWood) +* Support generating schema for Generic fields, [#2262](https://github.com/pydantic/pydantic/issues/2262) by [@maximberg](https://github.com/maximberg) +* Fix `validate_decorator` so `**kwargs` doesn't exclude values when the keyword + has the same name as the `*args` or `**kwargs` names, [#2251](https://github.com/pydantic/pydantic/issues/2251) by [@cybojenix](https://github.com/cybojenix) +* Prevent overriding positional arguments with keyword arguments in + `validate_arguments`, as per behaviour with native functions, [#2249](https://github.com/pydantic/pydantic/issues/2249) by [@cybojenix](https://github.com/cybojenix) +* add documentation for `con*` type functions, [#2242](https://github.com/pydantic/pydantic/issues/2242) by [@tayoogunbiyi](https://github.com/tayoogunbiyi) +* Support custom root type (aka `__root__`) when using `parse_obj()` with nested models, [#2238](https://github.com/pydantic/pydantic/issues/2238) by [@PrettyWood](https://github.com/PrettyWood) +* Support custom root type (aka `__root__`) with `from_orm()`, [#2237](https://github.com/pydantic/pydantic/issues/2237) by [@PrettyWood](https://github.com/PrettyWood) +* ensure cythonized functions are left untouched when creating models, based on [#1944](https://github.com/pydantic/pydantic/issues/1944) by [@kollmats](https://github.com/kollmats), [#2228](https://github.com/pydantic/pydantic/issues/2228) by [@samuelcolvin](https://github.com/samuelcolvin) +* Resolve forward refs for stdlib dataclasses converted into _pydantic_ ones, [#2220](https://github.com/pydantic/pydantic/issues/2220) by [@PrettyWood](https://github.com/PrettyWood) +* Add support for `NamedTuple` and `TypedDict` types. + Those two types are now handled and validated when used inside `BaseModel` or _pydantic_ `dataclass`. + Two utils are also added `create_model_from_namedtuple` and `create_model_from_typeddict`, [#2216](https://github.com/pydantic/pydantic/issues/2216) by [@PrettyWood](https://github.com/PrettyWood) +* Do not ignore annotated fields when type is `Union[Type[...], ...]`, [#2213](https://github.com/pydantic/pydantic/issues/2213) by [@PrettyWood](https://github.com/PrettyWood) +* Raise a user-friendly `TypeError` when a `root_validator` does not return a `dict` (e.g. `None`), [#2209](https://github.com/pydantic/pydantic/issues/2209) by [@masalim2](https://github.com/masalim2) +* Add a `FrozenSet[str]` type annotation to the `allowed_schemes` argument on the `strict_url` field type, [#2198](https://github.com/pydantic/pydantic/issues/2198) by [@Midnighter](https://github.com/Midnighter) +* add `allow_mutation` constraint to `Field`, [#2195](https://github.com/pydantic/pydantic/issues/2195) by [@sblack-usu](https://github.com/sblack-usu) +* Allow `Field` with a `default_factory` to be used as an argument to a function + decorated with `validate_arguments`, [#2176](https://github.com/pydantic/pydantic/issues/2176) by [@thomascobb](https://github.com/thomascobb) +* Allow non-existent secrets directory by only issuing a warning, [#2175](https://github.com/pydantic/pydantic/issues/2175) by [@davidolrik](https://github.com/davidolrik) +* fix URL regex to parse fragment without query string, [#2168](https://github.com/pydantic/pydantic/issues/2168) by [@andrewmwhite](https://github.com/andrewmwhite) +* fix: ensure to always return one of the values in `Literal` field type, [#2166](https://github.com/pydantic/pydantic/issues/2166) by [@PrettyWood](https://github.com/PrettyWood) +* Support `typing.Annotated` hints on model fields. A `Field` may now be set in the type hint with `Annotated[..., Field(...)`; all other annotations are ignored but still visible with `get_type_hints(..., include_extras=True)`, [#2147](https://github.com/pydantic/pydantic/issues/2147) by [@JacobHayes](https://github.com/JacobHayes) +* Added `StrictBytes` type as well as `strict=False` option to `ConstrainedBytes`, [#2136](https://github.com/pydantic/pydantic/issues/2136) by [@rlizzo](https://github.com/rlizzo) +* added `Config.anystr_lower` and `to_lower` kwarg to `constr` and `conbytes`, [#2134](https://github.com/pydantic/pydantic/issues/2134) by [@tayoogunbiyi](https://github.com/tayoogunbiyi) +* Support plain `typing.Tuple` type, [#2132](https://github.com/pydantic/pydantic/issues/2132) by [@PrettyWood](https://github.com/PrettyWood) +* Add a bound method `validate` to functions decorated with `validate_arguments` + to validate parameters without actually calling the function, [#2127](https://github.com/pydantic/pydantic/issues/2127) by [@PrettyWood](https://github.com/PrettyWood) +* Add the ability to customize settings sources (add / disable / change priority order), [#2107](https://github.com/pydantic/pydantic/issues/2107) by [@kozlek](https://github.com/kozlek) +* Fix mypy complaints about most custom _pydantic_ types, [#2098](https://github.com/pydantic/pydantic/issues/2098) by [@PrettyWood](https://github.com/PrettyWood) +* Add a [Hypothesis](https://hypothesis.readthedocs.io/) plugin for easier [property-based testing](https://increment.com/testing/in-praise-of-property-based-testing/) with Pydantic's custom types - [usage details here](https://pydantic-docs.helpmanual.io/hypothesis_plugin/), [#2097](https://github.com/pydantic/pydantic/issues/2097) by [@Zac-HD](https://github.com/Zac-HD) +* add validator for `None`, `NoneType` or `Literal[None]`, [#2095](https://github.com/pydantic/pydantic/issues/2095) by [@PrettyWood](https://github.com/PrettyWood) +* Handle properly fields of type `Callable` with a default value, [#2094](https://github.com/pydantic/pydantic/issues/2094) by [@PrettyWood](https://github.com/PrettyWood) +* Updated `create_model` return type annotation to return type which inherits from `__base__` argument, [#2071](https://github.com/pydantic/pydantic/issues/2071) by [@uriyyo](https://github.com/uriyyo) +* Add merged `json_encoders` inheritance, [#2064](https://github.com/pydantic/pydantic/issues/2064) by [@art049](https://github.com/art049) +* allow overwriting `ClassVar`s in sub-models without having to re-annotate them, [#2061](https://github.com/pydantic/pydantic/issues/2061) by [@layday](https://github.com/layday) +* add default encoder for `Pattern` type, [#2045](https://github.com/pydantic/pydantic/issues/2045) by [@PrettyWood](https://github.com/PrettyWood) +* Add `NonNegativeInt`, `NonPositiveInt`, `NonNegativeFloat`, `NonPositiveFloat`, [#1975](https://github.com/pydantic/pydantic/issues/1975) by [@mdavis-xyz](https://github.com/mdavis-xyz) +* Use % for percentage in string format of colors, [#1960](https://github.com/pydantic/pydantic/issues/1960) by [@EdwardBetts](https://github.com/EdwardBetts) +* Fixed issue causing `KeyError` to be raised when building schema from multiple `BaseModel` with the same names declared in separate classes, [#1912](https://github.com/pydantic/pydantic/issues/1912) by [@JSextonn](https://github.com/JSextonn) +* Add `rediss` (Redis over SSL) protocol to `RedisDsn` + Allow URLs without `user` part (e.g., `rediss://:pass@localhost`), [#1911](https://github.com/pydantic/pydantic/issues/1911) by [@TrDex](https://github.com/TrDex) +* Add a new `frozen` boolean parameter to `Config` (default: `False`). + Setting `frozen=True` does everything that `allow_mutation=False` does, and also generates a `__hash__()` method for the model. This makes instances of the model potentially hashable if all the attributes are hashable, [#1880](https://github.com/pydantic/pydantic/issues/1880) by [@rhuille](https://github.com/rhuille) +* fix schema generation with multiple Enums having the same name, [#1857](https://github.com/pydantic/pydantic/issues/1857) by [@PrettyWood](https://github.com/PrettyWood) +* Added support for 13/19 digits VISA credit cards in `PaymentCardNumber` type, [#1416](https://github.com/pydantic/pydantic/issues/1416) by [@AlexanderSov](https://github.com/AlexanderSov) +* fix: prevent `RecursionError` while using recursive `GenericModel`s, [#1370](https://github.com/pydantic/pydantic/issues/1370) by [@xppt](https://github.com/xppt) +* use `enum` for `typing.Literal` in JSON schema, [#1350](https://github.com/pydantic/pydantic/issues/1350) by [@PrettyWood](https://github.com/PrettyWood) +* Fix: some recursive models did not require `update_forward_refs` and silently behaved incorrectly, [#1201](https://github.com/pydantic/pydantic/issues/1201) by [@PrettyWood](https://github.com/PrettyWood) +* Fix bug where generic models with fields where the typevar is nested in another type `a: List[T]` are considered to be concrete. This allows these models to be subclassed and composed as expected, [#947](https://github.com/pydantic/pydantic/issues/947) by [@daviskirk](https://github.com/daviskirk) +* Add `Config.copy_on_model_validation` flag. When set to `False`, _pydantic_ will keep models used as fields + untouched on validation instead of reconstructing (copying) them, [#265](https://github.com/pydantic/pydantic/issues/265) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7.4 (2021-05-11) + +* **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` + (or their negative values) does not cause an infinite loop, + See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) + +## v1.7.3 (2020-11-30) + +Thank you to pydantic's sponsors: +@timdrijvers, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api), +@mkeen, [@meadsteve](https://github.com/meadsteve) for their kind support. + +* fix: set right default value for required (optional) fields, [#2142](https://github.com/pydantic/pydantic/issues/2142) by [@PrettyWood](https://github.com/PrettyWood) +* fix: support `underscore_attrs_are_private` with generic models, [#2138](https://github.com/pydantic/pydantic/issues/2138) by [@PrettyWood](https://github.com/PrettyWood) +* fix: update all modified field values in `root_validator` when `validate_assignment` is on, [#2116](https://github.com/pydantic/pydantic/issues/2116) by [@PrettyWood](https://github.com/PrettyWood) +* Allow pickling of `pydantic.dataclasses.dataclass` dynamically created from a built-in `dataclasses.dataclass`, [#2111](https://github.com/pydantic/pydantic/issues/2111) by [@aimestereo](https://github.com/aimestereo) +* Fix a regression where Enum fields would not propagate keyword arguments to the schema, [#2109](https://github.com/pydantic/pydantic/issues/2109) by [@bm424](https://github.com/bm424) +* Ignore `__doc__` as private attribute when `Config.underscore_attrs_are_private` is set, [#2090](https://github.com/pydantic/pydantic/issues/2090) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7.2 (2020-11-01) + +* fix slow `GenericModel` concrete model creation, allow `GenericModel` concrete name reusing in module, [#2078](https://github.com/pydantic/pydantic/issues/2078) by [@Bobronium](https://github.com/Bobronium) +* keep the order of the fields when `validate_assignment` is set, [#2073](https://github.com/pydantic/pydantic/issues/2073) by [@PrettyWood](https://github.com/PrettyWood) +* forward all the params of the stdlib `dataclass` when converted into _pydantic_ `dataclass`, [#2065](https://github.com/pydantic/pydantic/issues/2065) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7.1 (2020-10-28) + +Thank you to pydantic's sponsors: +@timdrijvers, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api), [@mkeen](https://github.com/mkeen) +for their kind support. + +* fix annotation of `validate_arguments` when passing configuration as argument, [#2055](https://github.com/pydantic/pydantic/issues/2055) by [@layday](https://github.com/layday) +* Fix mypy assignment error when using `PrivateAttr`, [#2048](https://github.com/pydantic/pydantic/issues/2048) by [@aphedges](https://github.com/aphedges) +* fix `underscore_attrs_are_private` causing `TypeError` when overriding `__init__`, [#2047](https://github.com/pydantic/pydantic/issues/2047) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fixed regression introduced in v1.7 involving exception handling in field validators when `validate_assignment=True`, [#2044](https://github.com/pydantic/pydantic/issues/2044) by [@johnsabath](https://github.com/johnsabath) +* fix: _pydantic_ `dataclass` can inherit from stdlib `dataclass` + and `Config.arbitrary_types_allowed` is supported, [#2042](https://github.com/pydantic/pydantic/issues/2042) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7 (2020-10-26) + +Thank you to pydantic's sponsors: +@timdrijvers, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api) +for their kind support. + +### Highlights + +* Python 3.9 support, thanks [@PrettyWood](https://github.com/PrettyWood) +* [Private model attributes](https://pydantic-docs.helpmanual.io/usage/models/#private-model-attributes), thanks [@Bobronium](https://github.com/Bobronium) +* ["secrets files" support in `BaseSettings`](https://pydantic-docs.helpmanual.io/usage/settings/#secret-support), thanks [@mdgilene](https://github.com/mdgilene) +* [convert stdlib dataclasses to pydantic dataclasses and use stdlib dataclasses in models](https://pydantic-docs.helpmanual.io/usage/dataclasses/#stdlib-dataclasses-and-pydantic-dataclasses), thanks [@PrettyWood](https://github.com/PrettyWood) + +### Changes + +* **Breaking Change:** remove `__field_defaults__`, add `default_factory` support with `BaseModel.construct`. + Use `.get_default()` method on fields in `__fields__` attribute instead, [#1732](https://github.com/pydantic/pydantic/issues/1732) by [@PrettyWood](https://github.com/PrettyWood) +* Rearrange CI to run linting as a separate job, split install recipes for different tasks, [#2020](https://github.com/pydantic/pydantic/issues/2020) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allows subclasses of generic models to make some, or all, of the superclass's type parameters concrete, while + also defining new type parameters in the subclass, [#2005](https://github.com/pydantic/pydantic/issues/2005) by [@choogeboom](https://github.com/choogeboom) +* Call validator with the correct `values` parameter type in `BaseModel.__setattr__`, + when `validate_assignment = True` in model config, [#1999](https://github.com/pydantic/pydantic/issues/1999) by [@me-ransh](https://github.com/me-ransh) +* Force `fields.Undefined` to be a singleton object, fixing inherited generic model schemas, [#1981](https://github.com/pydantic/pydantic/issues/1981) by [@daviskirk](https://github.com/daviskirk) +* Include tests in source distributions, [#1976](https://github.com/pydantic/pydantic/issues/1976) by [@sbraz](https://github.com/sbraz) +* Add ability to use `min_length/max_length` constraints with secret types, [#1974](https://github.com/pydantic/pydantic/issues/1974) by [@uriyyo](https://github.com/uriyyo) +* Also check `root_validators` when `validate_assignment` is on, [#1971](https://github.com/pydantic/pydantic/issues/1971) by [@PrettyWood](https://github.com/PrettyWood) +* Fix const validators not running when custom validators are present, [#1957](https://github.com/pydantic/pydantic/issues/1957) by [@hmvp](https://github.com/hmvp) +* add `deque` to field types, [#1935](https://github.com/pydantic/pydantic/issues/1935) by [@wozniakty](https://github.com/wozniakty) +* add basic support for Python 3.9, [#1832](https://github.com/pydantic/pydantic/issues/1832) by [@PrettyWood](https://github.com/PrettyWood) +* Fix typo in the anchor of exporting_models.md#modelcopy and incorrect description, [#1821](https://github.com/pydantic/pydantic/issues/1821) by [@KimMachineGun](https://github.com/KimMachineGun) +* Added ability for `BaseSettings` to read "secret files", [#1820](https://github.com/pydantic/pydantic/issues/1820) by [@mdgilene](https://github.com/mdgilene) +* add `parse_raw_as` utility function, [#1812](https://github.com/pydantic/pydantic/issues/1812) by [@PrettyWood](https://github.com/PrettyWood) +* Support home directory relative paths for `dotenv` files (e.g. `~/.env`), [#1803](https://github.com/pydantic/pydantic/issues/1803) by [@PrettyWood](https://github.com/PrettyWood) +* Clarify documentation for `parse_file` to show that the argument + should be a file *path* not a file-like object, [#1794](https://github.com/pydantic/pydantic/issues/1794) by [@mdavis-xyz](https://github.com/mdavis-xyz) +* Fix false positive from mypy plugin when a class nested within a `BaseModel` is named `Model`, [#1770](https://github.com/pydantic/pydantic/issues/1770) by [@selimb](https://github.com/selimb) +* add basic support of Pattern type in schema generation, [#1767](https://github.com/pydantic/pydantic/issues/1767) by [@PrettyWood](https://github.com/PrettyWood) +* Support custom title, description and default in schema of enums, [#1748](https://github.com/pydantic/pydantic/issues/1748) by [@PrettyWood](https://github.com/PrettyWood) +* Properly represent `Literal` Enums when `use_enum_values` is True, [#1747](https://github.com/pydantic/pydantic/issues/1747) by [@noelevans](https://github.com/noelevans) +* Allows timezone information to be added to strings to be formatted as time objects. Permitted formats are `Z` for UTC + or an offset for absolute positive or negative time shifts. Or the timezone data can be omitted, [#1744](https://github.com/pydantic/pydantic/issues/1744) by [@noelevans](https://github.com/noelevans) +* Add stub `__init__` with Python 3.6 signature for `ForwardRef`, [#1738](https://github.com/pydantic/pydantic/issues/1738) by [@sirtelemak](https://github.com/sirtelemak) +* Fix behaviour with forward refs and optional fields in nested models, [#1736](https://github.com/pydantic/pydantic/issues/1736) by [@PrettyWood](https://github.com/PrettyWood) +* add `Enum` and `IntEnum` as valid types for fields, [#1735](https://github.com/pydantic/pydantic/issues/1735) by [@PrettyWood](https://github.com/PrettyWood) +* Change default value of `__module__` argument of `create_model` from `None` to `'pydantic.main'`. + Set reference of created concrete model to it's module to allow pickling (not applied to models created in + functions), [#1686](https://github.com/pydantic/pydantic/issues/1686) by [@Bobronium](https://github.com/Bobronium) +* Add private attributes support, [#1679](https://github.com/pydantic/pydantic/issues/1679) by [@Bobronium](https://github.com/Bobronium) +* add `config` to `@validate_arguments`, [#1663](https://github.com/pydantic/pydantic/issues/1663) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allow descendant Settings models to override env variable names for the fields defined in parent Settings models with + `env` in their `Config`. Previously only `env_prefix` configuration option was applicable, [#1561](https://github.com/pydantic/pydantic/issues/1561) by [@ojomio](https://github.com/ojomio) +* Support `ref_template` when creating schema `$ref`s, [#1479](https://github.com/pydantic/pydantic/issues/1479) by [@kilo59](https://github.com/kilo59) +* Add a `__call__` stub to `PyObject` so that mypy will know that it is callable, [#1352](https://github.com/pydantic/pydantic/issues/1352) by [@brianmaissy](https://github.com/brianmaissy) +* `pydantic.dataclasses.dataclass` decorator now supports built-in `dataclasses.dataclass`. + It is hence possible to convert an existing `dataclass` easily to add *pydantic* validation. + Moreover nested dataclasses are also supported, [#744](https://github.com/pydantic/pydantic/issues/744) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.6.2 (2021-05-11) + +* **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` + (or their negative values) does not cause an infinite loop, + See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) + +## v1.6.1 (2020-07-15) + +* fix validation and parsing of nested models with `default_factory`, [#1710](https://github.com/pydantic/pydantic/issues/1710) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.6 (2020-07-11) + +Thank you to pydantic's sponsors: [@matin](https://github.com/matin), [@tiangolo](https://github.com/tiangolo), [@chdsbd](https://github.com/chdsbd), [@jorgecarleitao](https://github.com/jorgecarleitao), and 1 anonymous sponsor for their kind support. + +* Modify validators for `conlist` and `conset` to not have `always=True`, [#1682](https://github.com/pydantic/pydantic/issues/1682) by [@samuelcolvin](https://github.com/samuelcolvin) +* add port check to `AnyUrl` (can't exceed 65536) ports are 16 insigned bits: `0 <= port <= 2**16-1` src: [rfc793 header format](https://tools.ietf.org/html/rfc793#section-3.1), [#1654](https://github.com/pydantic/pydantic/issues/1654) by [@flapili](https://github.com/flapili) +* Document default `regex` anchoring semantics, [#1648](https://github.com/pydantic/pydantic/issues/1648) by [@yurikhan](https://github.com/yurikhan) +* Use `chain.from_iterable` in class_validators.py. This is a faster and more idiomatic way of using `itertools.chain`. + Instead of computing all the items in the iterable and storing them in memory, they are computed one-by-one and never + stored as a huge list. This can save on both runtime and memory space, [#1642](https://github.com/pydantic/pydantic/issues/1642) by [@cool-RR](https://github.com/cool-RR) +* Add `conset()`, analogous to `conlist()`, [#1623](https://github.com/pydantic/pydantic/issues/1623) by [@patrickkwang](https://github.com/patrickkwang) +* make *pydantic* errors (un)pickable, [#1616](https://github.com/pydantic/pydantic/issues/1616) by [@PrettyWood](https://github.com/PrettyWood) +* Allow custom encoding for `dotenv` files, [#1615](https://github.com/pydantic/pydantic/issues/1615) by [@PrettyWood](https://github.com/PrettyWood) +* Ensure `SchemaExtraCallable` is always defined to get type hints on BaseConfig, [#1614](https://github.com/pydantic/pydantic/issues/1614) by [@PrettyWood](https://github.com/PrettyWood) +* Update datetime parser to support negative timestamps, [#1600](https://github.com/pydantic/pydantic/issues/1600) by [@mlbiche](https://github.com/mlbiche) +* Update mypy, remove `AnyType` alias for `Type[Any]`, [#1598](https://github.com/pydantic/pydantic/issues/1598) by [@samuelcolvin](https://github.com/samuelcolvin) +* Adjust handling of root validators so that errors are aggregated from _all_ failing root validators, instead of reporting on only the first root validator to fail, [#1586](https://github.com/pydantic/pydantic/issues/1586) by [@beezee](https://github.com/beezee) +* Make `__modify_schema__` on Enums apply to the enum schema rather than fields that use the enum, [#1581](https://github.com/pydantic/pydantic/issues/1581) by [@therefromhere](https://github.com/therefromhere) +* Fix behavior of `__all__` key when used in conjunction with index keys in advanced include/exclude of fields that are sequences, [#1579](https://github.com/pydantic/pydantic/issues/1579) by [@xspirus](https://github.com/xspirus) +* Subclass validators do not run when referencing a `List` field defined in a parent class when `each_item=True`. Added an example to the docs illustrating this, [#1566](https://github.com/pydantic/pydantic/issues/1566) by [@samueldeklund](https://github.com/samueldeklund) +* change `schema.field_class_to_schema` to support `frozenset` in schema, [#1557](https://github.com/pydantic/pydantic/issues/1557) by [@wangpeibao](https://github.com/wangpeibao) +* Call `__modify_schema__` only for the field schema, [#1552](https://github.com/pydantic/pydantic/issues/1552) by [@PrettyWood](https://github.com/PrettyWood) +* Move the assignment of `field.validate_always` in `fields.py` so the `always` parameter of validators work on inheritance, [#1545](https://github.com/pydantic/pydantic/issues/1545) by [@dcHHH](https://github.com/dcHHH) +* Added support for UUID instantiation through 16 byte strings such as `b'\x12\x34\x56\x78' * 4`. This was done to support `BINARY(16)` columns in sqlalchemy, [#1541](https://github.com/pydantic/pydantic/issues/1541) by [@shawnwall](https://github.com/shawnwall) +* Add a test assertion that `default_factory` can return a singleton, [#1523](https://github.com/pydantic/pydantic/issues/1523) by [@therefromhere](https://github.com/therefromhere) +* Add `NameEmail.__eq__` so duplicate `NameEmail` instances are evaluated as equal, [#1514](https://github.com/pydantic/pydantic/issues/1514) by [@stephen-bunn](https://github.com/stephen-bunn) +* Add datamodel-code-generator link in pydantic document site, [#1500](https://github.com/pydantic/pydantic/issues/1500) by [@koxudaxi](https://github.com/koxudaxi) +* Added a "Discussion of Pydantic" section to the documentation, with a link to "Pydantic Introduction" video by Alexander Hultnér, [#1499](https://github.com/pydantic/pydantic/issues/1499) by [@hultner](https://github.com/hultner) +* Avoid some side effects of `default_factory` by calling it only once + if possible and by not setting a default value in the schema, [#1491](https://github.com/pydantic/pydantic/issues/1491) by [@PrettyWood](https://github.com/PrettyWood) +* Added docs about dumping dataclasses to JSON, [#1487](https://github.com/pydantic/pydantic/issues/1487) by [@mikegrima](https://github.com/mikegrima) +* Make `BaseModel.__signature__` class-only, so getting `__signature__` from model instance will raise `AttributeError`, [#1466](https://github.com/pydantic/pydantic/issues/1466) by [@Bobronium](https://github.com/Bobronium) +* include `'format': 'password'` in the schema for secret types, [#1424](https://github.com/pydantic/pydantic/issues/1424) by [@atheuz](https://github.com/atheuz) +* Modify schema constraints on `ConstrainedFloat` so that `exclusiveMinimum` and + minimum are not included in the schema if they are equal to `-math.inf` and + `exclusiveMaximum` and `maximum` are not included if they are equal to `math.inf`, [#1417](https://github.com/pydantic/pydantic/issues/1417) by [@vdwees](https://github.com/vdwees) +* Squash internal `__root__` dicts in `.dict()` (and, by extension, in `.json()`), [#1414](https://github.com/pydantic/pydantic/issues/1414) by [@patrickkwang](https://github.com/patrickkwang) +* Move `const` validator to post-validators so it validates the parsed value, [#1410](https://github.com/pydantic/pydantic/issues/1410) by [@selimb](https://github.com/selimb) +* Fix model validation to handle nested literals, e.g. `Literal['foo', Literal['bar']]`, [#1364](https://github.com/pydantic/pydantic/issues/1364) by [@DBCerigo](https://github.com/DBCerigo) +* Remove `user_required = True` from `RedisDsn`, neither user nor password are required, [#1275](https://github.com/pydantic/pydantic/issues/1275) by [@samuelcolvin](https://github.com/samuelcolvin) +* Remove extra `allOf` from schema for fields with `Union` and custom `Field`, [#1209](https://github.com/pydantic/pydantic/issues/1209) by [@mostaphaRoudsari](https://github.com/mostaphaRoudsari) +* Updates OpenAPI schema generation to output all enums as separate models. + Instead of inlining the enum values in the model schema, models now use a `$ref` + property to point to the enum definition, [#1173](https://github.com/pydantic/pydantic/issues/1173) by [@calvinwyoung](https://github.com/calvinwyoung) + +## v1.5.1 (2020-04-23) + +* Signature generation with `extra: allow` never uses a field name, [#1418](https://github.com/pydantic/pydantic/issues/1418) by [@prettywood](https://github.com/prettywood) +* Avoid mutating `Field` default value, [#1412](https://github.com/pydantic/pydantic/issues/1412) by [@prettywood](https://github.com/prettywood) + +## v1.5 (2020-04-18) + +* Make includes/excludes arguments for `.dict()`, `._iter()`, ..., immutable, [#1404](https://github.com/pydantic/pydantic/issues/1404) by [@AlexECX](https://github.com/AlexECX) +* Always use a field's real name with includes/excludes in `model._iter()`, regardless of `by_alias`, [#1397](https://github.com/pydantic/pydantic/issues/1397) by [@AlexECX](https://github.com/AlexECX) +* Update constr regex example to include start and end lines, [#1396](https://github.com/pydantic/pydantic/issues/1396) by [@lmcnearney](https://github.com/lmcnearney) +* Confirm that shallow `model.copy()` does make a shallow copy of attributes, [#1383](https://github.com/pydantic/pydantic/issues/1383) by [@samuelcolvin](https://github.com/samuelcolvin) +* Renaming `model_name` argument of `main.create_model()` to `__model_name` to allow using `model_name` as a field name, [#1367](https://github.com/pydantic/pydantic/issues/1367) by [@kittipatv](https://github.com/kittipatv) +* Replace raising of exception to silent passing for non-Var attributes in mypy plugin, [#1345](https://github.com/pydantic/pydantic/issues/1345) by [@b0g3r](https://github.com/b0g3r) +* Remove `typing_extensions` dependency for Python 3.8, [#1342](https://github.com/pydantic/pydantic/issues/1342) by [@prettywood](https://github.com/prettywood) +* Make `SecretStr` and `SecretBytes` initialization idempotent, [#1330](https://github.com/pydantic/pydantic/issues/1330) by [@atheuz](https://github.com/atheuz) +* document making secret types dumpable using the json method, [#1328](https://github.com/pydantic/pydantic/issues/1328) by [@atheuz](https://github.com/atheuz) +* Move all testing and build to github actions, add windows and macos binaries, + thank you [@StephenBrown2](https://github.com/StephenBrown2) for much help, [#1326](https://github.com/pydantic/pydantic/issues/1326) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix card number length check in `PaymentCardNumber`, `PaymentCardBrand` now inherits from `str`, [#1317](https://github.com/pydantic/pydantic/issues/1317) by [@samuelcolvin](https://github.com/samuelcolvin) +* Have `BaseModel` inherit from `Representation` to make mypy happy when overriding `__str__`, [#1310](https://github.com/pydantic/pydantic/issues/1310) by [@FuegoFro](https://github.com/FuegoFro) +* Allow `None` as input to all optional list fields, [#1307](https://github.com/pydantic/pydantic/issues/1307) by [@prettywood](https://github.com/prettywood) +* Add `datetime` field to `default_factory` example, [#1301](https://github.com/pydantic/pydantic/issues/1301) by [@StephenBrown2](https://github.com/StephenBrown2) +* Allow subclasses of known types to be encoded with superclass encoder, [#1291](https://github.com/pydantic/pydantic/issues/1291) by [@StephenBrown2](https://github.com/StephenBrown2) +* Exclude exported fields from all elements of a list/tuple of submodels/dicts with `'__all__'`, [#1286](https://github.com/pydantic/pydantic/issues/1286) by [@masalim2](https://github.com/masalim2) +* Add pydantic.color.Color objects as available input for Color fields, [#1258](https://github.com/pydantic/pydantic/issues/1258) by [@leosussan](https://github.com/leosussan) +* In examples, type nullable fields as `Optional`, so that these are valid mypy annotations, [#1248](https://github.com/pydantic/pydantic/issues/1248) by [@kokes](https://github.com/kokes) +* Make `pattern_validator()` accept pre-compiled `Pattern` objects. Fix `str_validator()` return type to `str`, [#1237](https://github.com/pydantic/pydantic/issues/1237) by [@adamgreg](https://github.com/adamgreg) +* Document how to manage Generics and inheritance, [#1229](https://github.com/pydantic/pydantic/issues/1229) by [@esadruhn](https://github.com/esadruhn) +* `update_forward_refs()` method of BaseModel now copies `__dict__` of class module instead of modyfying it, [#1228](https://github.com/pydantic/pydantic/issues/1228) by [@paul-ilyin](https://github.com/paul-ilyin) +* Support instance methods and class methods with `@validate_arguments`, [#1222](https://github.com/pydantic/pydantic/issues/1222) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `default_factory` argument to `Field` to create a dynamic default value by passing a zero-argument callable, [#1210](https://github.com/pydantic/pydantic/issues/1210) by [@prettywood](https://github.com/prettywood) +* add support for `NewType` of `List`, `Optional`, etc, [#1207](https://github.com/pydantic/pydantic/issues/1207) by [@Kazy](https://github.com/Kazy) +* fix mypy signature for `root_validator`, [#1192](https://github.com/pydantic/pydantic/issues/1192) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fixed parsing of nested 'custom root type' models, [#1190](https://github.com/pydantic/pydantic/issues/1190) by [@Shados](https://github.com/Shados) +* Add `validate_arguments` function decorator which checks the arguments to a function matches type annotations, [#1179](https://github.com/pydantic/pydantic/issues/1179) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `__signature__` to models, [#1034](https://github.com/pydantic/pydantic/issues/1034) by [@Bobronium](https://github.com/Bobronium) +* Refactor `._iter()` method, 10x speed boost for `dict(model)`, [#1017](https://github.com/pydantic/pydantic/issues/1017) by [@Bobronium](https://github.com/Bobronium) + +## v1.4 (2020-01-24) + +* **Breaking Change:** alias precedence logic changed so aliases on a field always take priority over + an alias from `alias_generator` to avoid buggy/unexpected behaviour, + see [here](https://pydantic-docs.helpmanual.io/usage/model_config/#alias-precedence) for details, [#1178](https://github.com/pydantic/pydantic/issues/1178) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for unicode and punycode in TLDs, [#1182](https://github.com/pydantic/pydantic/issues/1182) by [@jamescurtin](https://github.com/jamescurtin) +* Fix `cls` argument in validators during assignment, [#1172](https://github.com/pydantic/pydantic/issues/1172) by [@samuelcolvin](https://github.com/samuelcolvin) +* completing Luhn algorithm for `PaymentCardNumber`, [#1166](https://github.com/pydantic/pydantic/issues/1166) by [@cuencandres](https://github.com/cuencandres) +* add support for generics that implement `__get_validators__` like a custom data type, [#1159](https://github.com/pydantic/pydantic/issues/1159) by [@tiangolo](https://github.com/tiangolo) +* add support for infinite generators with `Iterable`, [#1152](https://github.com/pydantic/pydantic/issues/1152) by [@tiangolo](https://github.com/tiangolo) +* fix `url_regex` to accept schemas with `+`, `-` and `.` after the first character, [#1142](https://github.com/pydantic/pydantic/issues/1142) by [@samuelcolvin](https://github.com/samuelcolvin) +* move `version_info()` to `version.py`, suggest its use in issues, [#1138](https://github.com/pydantic/pydantic/issues/1138) by [@samuelcolvin](https://github.com/samuelcolvin) +* Improve pydantic import time by roughly 50% by deferring some module loading and regex compilation, [#1127](https://github.com/pydantic/pydantic/issues/1127) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix `EmailStr` and `NameEmail` to accept instances of themselves in cython, [#1126](https://github.com/pydantic/pydantic/issues/1126) by [@koxudaxi](https://github.com/koxudaxi) +* Pass model class to the `Config.schema_extra` callable, [#1125](https://github.com/pydantic/pydantic/issues/1125) by [@therefromhere](https://github.com/therefromhere) +* Fix regex for username and password in URLs, [#1115](https://github.com/pydantic/pydantic/issues/1115) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for nested generic models, [#1104](https://github.com/pydantic/pydantic/issues/1104) by [@dmontagu](https://github.com/dmontagu) +* add `__all__` to `__init__.py` to prevent "implicit reexport" errors from mypy, [#1072](https://github.com/pydantic/pydantic/issues/1072) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for using "dotenv" files with `BaseSettings`, [#1011](https://github.com/pydantic/pydantic/issues/1011) by [@acnebs](https://github.com/acnebs) + +## v1.3 (2019-12-21) + +* Change `schema` and `schema_model` to handle dataclasses by using their `__pydantic_model__` feature, [#792](https://github.com/pydantic/pydantic/issues/792) by [@aviramha](https://github.com/aviramha) +* Added option for `root_validator` to be skipped if values validation fails using keyword `skip_on_failure=True`, [#1049](https://github.com/pydantic/pydantic/issues/1049) by [@aviramha](https://github.com/aviramha) +* Allow `Config.schema_extra` to be a callable so that the generated schema can be post-processed, [#1054](https://github.com/pydantic/pydantic/issues/1054) by [@selimb](https://github.com/selimb) +* Update mypy to version 0.750, [#1057](https://github.com/pydantic/pydantic/issues/1057) by [@dmontagu](https://github.com/dmontagu) +* Trick Cython into allowing str subclassing, [#1061](https://github.com/pydantic/pydantic/issues/1061) by [@skewty](https://github.com/skewty) +* Prevent type attributes being added to schema unless the attribute `__schema_attributes__` is `True`, [#1064](https://github.com/pydantic/pydantic/issues/1064) by [@samuelcolvin](https://github.com/samuelcolvin) +* Change `BaseModel.parse_file` to use `Config.json_loads`, [#1067](https://github.com/pydantic/pydantic/issues/1067) by [@kierandarcy](https://github.com/kierandarcy) +* Fix for optional `Json` fields, [#1073](https://github.com/pydantic/pydantic/issues/1073) by [@volker48](https://github.com/volker48) +* Change the default number of threads used when compiling with cython to one, + allow override via the `CYTHON_NTHREADS` environment variable, [#1074](https://github.com/pydantic/pydantic/issues/1074) by [@samuelcolvin](https://github.com/samuelcolvin) +* Run FastAPI tests during Pydantic's CI tests, [#1075](https://github.com/pydantic/pydantic/issues/1075) by [@tiangolo](https://github.com/tiangolo) +* My mypy strictness constraints, and associated tweaks to type annotations, [#1077](https://github.com/pydantic/pydantic/issues/1077) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `__eq__` to SecretStr and SecretBytes to allow "value equals", [#1079](https://github.com/pydantic/pydantic/issues/1079) by [@sbv-trueenergy](https://github.com/sbv-trueenergy) +* Fix schema generation for nested None case, [#1088](https://github.com/pydantic/pydantic/issues/1088) by [@lutostag](https://github.com/lutostag) +* Consistent checks for sequence like objects, [#1090](https://github.com/pydantic/pydantic/issues/1090) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix `Config` inheritance on `BaseSettings` when used with `env_prefix`, [#1091](https://github.com/pydantic/pydantic/issues/1091) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix for `__modify_schema__` when it conflicted with `field_class_to_schema*`, [#1102](https://github.com/pydantic/pydantic/issues/1102) by [@samuelcolvin](https://github.com/samuelcolvin) +* docs: Fix explanation of case sensitive environment variable names when populating `BaseSettings` subclass attributes, [#1105](https://github.com/pydantic/pydantic/issues/1105) by [@tribals](https://github.com/tribals) +* Rename django-rest-framework benchmark in documentation, [#1119](https://github.com/pydantic/pydantic/issues/1119) by [@frankie567](https://github.com/frankie567) + +## v1.2 (2019-11-28) + +* **Possible Breaking Change:** Add support for required `Optional` with `name: Optional[AnyType] = Field(...)` + and refactor `ModelField` creation to preserve `required` parameter value, [#1031](https://github.com/pydantic/pydantic/issues/1031) by [@tiangolo](https://github.com/tiangolo); + see [here](https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields) for details +* Add benchmarks for `cattrs`, [#513](https://github.com/pydantic/pydantic/issues/513) by [@sebastianmika](https://github.com/sebastianmika) +* Add `exclude_none` option to `dict()` and friends, [#587](https://github.com/pydantic/pydantic/issues/587) by [@niknetniko](https://github.com/niknetniko) +* Add benchmarks for `valideer`, [#670](https://github.com/pydantic/pydantic/issues/670) by [@gsakkis](https://github.com/gsakkis) +* Add `parse_obj_as` and `parse_file_as` functions for ad-hoc parsing of data into arbitrary pydantic-compatible types, [#934](https://github.com/pydantic/pydantic/issues/934) by [@dmontagu](https://github.com/dmontagu) +* Add `allow_reuse` argument to validators, thus allowing validator reuse, [#940](https://github.com/pydantic/pydantic/issues/940) by [@dmontagu](https://github.com/dmontagu) +* Add support for mapping types for custom root models, [#958](https://github.com/pydantic/pydantic/issues/958) by [@dmontagu](https://github.com/dmontagu) +* Mypy plugin support for dataclasses, [#966](https://github.com/pydantic/pydantic/issues/966) by [@koxudaxi](https://github.com/koxudaxi) +* Add support for dataclasses default factory, [#968](https://github.com/pydantic/pydantic/issues/968) by [@ahirner](https://github.com/ahirner) +* Add a `ByteSize` type for converting byte string (`1GB`) to plain bytes, [#977](https://github.com/pydantic/pydantic/issues/977) by [@dgasmith](https://github.com/dgasmith) +* Fix mypy complaint about `@root_validator(pre=True)`, [#984](https://github.com/pydantic/pydantic/issues/984) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add manylinux binaries for Python 3.8 to pypi, also support manylinux2010, [#994](https://github.com/pydantic/pydantic/issues/994) by [@samuelcolvin](https://github.com/samuelcolvin) +* Adds ByteSize conversion to another unit, [#995](https://github.com/pydantic/pydantic/issues/995) by [@dgasmith](https://github.com/dgasmith) +* Fix `__str__` and `__repr__` inheritance for models, [#1022](https://github.com/pydantic/pydantic/issues/1022) by [@samuelcolvin](https://github.com/samuelcolvin) +* add testimonials section to docs, [#1025](https://github.com/pydantic/pydantic/issues/1025) by [@sullivancolin](https://github.com/sullivancolin) +* Add support for `typing.Literal` for Python 3.8, [#1026](https://github.com/pydantic/pydantic/issues/1026) by [@dmontagu](https://github.com/dmontagu) + +## v1.1.1 (2019-11-20) + +* Fix bug where use of complex fields on sub-models could cause fields to be incorrectly configured, [#1015](https://github.com/pydantic/pydantic/issues/1015) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.1 (2019-11-07) + +* Add a mypy plugin for type checking `BaseModel.__init__` and more, [#722](https://github.com/pydantic/pydantic/issues/722) by [@dmontagu](https://github.com/dmontagu) +* Change return type typehint for `GenericModel.__class_getitem__` to prevent PyCharm warnings, [#936](https://github.com/pydantic/pydantic/issues/936) by [@dmontagu](https://github.com/dmontagu) +* Fix usage of `Any` to allow `None`, also support `TypeVar` thus allowing use of un-parameterised collection types + e.g. `Dict` and `List`, [#962](https://github.com/pydantic/pydantic/issues/962) by [@samuelcolvin](https://github.com/samuelcolvin) +* Set `FieldInfo` on subfields to fix schema generation for complex nested types, [#965](https://github.com/pydantic/pydantic/issues/965) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.0 (2019-10-23) + +* **Breaking Change:** deprecate the `Model.fields` property, use `Model.__fields__` instead, [#883](https://github.com/pydantic/pydantic/issues/883) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** Change the precedence of aliases so child model aliases override parent aliases, + including using `alias_generator`, [#904](https://github.com/pydantic/pydantic/issues/904) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking change:** Rename `skip_defaults` to `exclude_unset`, and add ability to exclude actual defaults, [#915](https://github.com/pydantic/pydantic/issues/915) by [@dmontagu](https://github.com/dmontagu) +* Add `**kwargs` to `pydantic.main.ModelMetaclass.__new__` so `__init_subclass__` can take custom parameters on extended + `BaseModel` classes, [#867](https://github.com/pydantic/pydantic/issues/867) by [@retnikt](https://github.com/retnikt) +* Fix field of a type that has a default value, [#880](https://github.com/pydantic/pydantic/issues/880) by [@koxudaxi](https://github.com/koxudaxi) +* Use `FutureWarning` instead of `DeprecationWarning` when `alias` instead of `env` is used for settings models, [#881](https://github.com/pydantic/pydantic/issues/881) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix issue with `BaseSettings` inheritance and `alias` getting set to `None`, [#882](https://github.com/pydantic/pydantic/issues/882) by [@samuelcolvin](https://github.com/samuelcolvin) +* Modify `__repr__` and `__str__` methods to be consistent across all public classes, add `__pretty__` to support + python-devtools, [#884](https://github.com/pydantic/pydantic/issues/884) by [@samuelcolvin](https://github.com/samuelcolvin) +* deprecation warning for `case_insensitive` on `BaseSettings` config, [#885](https://github.com/pydantic/pydantic/issues/885) by [@samuelcolvin](https://github.com/samuelcolvin) +* For `BaseSettings` merge environment variables and in-code values recursively, as long as they create a valid object + when merged together, to allow splitting init arguments, [#888](https://github.com/pydantic/pydantic/issues/888) by [@idmitrievsky](https://github.com/idmitrievsky) +* change secret types example, [#890](https://github.com/pydantic/pydantic/issues/890) by [@ashears](https://github.com/ashears) +* Change the signature of `Model.construct()` to be more user-friendly, document `construct()` usage, [#898](https://github.com/pydantic/pydantic/issues/898) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add example for the `construct()` method, [#907](https://github.com/pydantic/pydantic/issues/907) by [@ashears](https://github.com/ashears) +* Improve use of `Field` constraints on complex types, raise an error if constraints are not enforceable, + also support tuples with an ellipsis `Tuple[X, ...]`, `Sequence` and `FrozenSet` in schema, [#909](https://github.com/pydantic/pydantic/issues/909) by [@samuelcolvin](https://github.com/samuelcolvin) +* update docs for bool missing valid value, [#911](https://github.com/pydantic/pydantic/issues/911) by [@trim21](https://github.com/trim21) +* Better `str`/`repr` logic for `ModelField`, [#912](https://github.com/pydantic/pydantic/issues/912) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix `ConstrainedList`, update schema generation to reflect `min_items` and `max_items` `Field()` arguments, [#917](https://github.com/pydantic/pydantic/issues/917) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allow abstracts sets (eg. dict keys) in the `include` and `exclude` arguments of `dict()`, [#921](https://github.com/pydantic/pydantic/issues/921) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix JSON serialization errors on `ValidationError.json()` by using `pydantic_encoder`, [#922](https://github.com/pydantic/pydantic/issues/922) by [@samuelcolvin](https://github.com/samuelcolvin) +* Clarify usage of `remove_untouched`, improve error message for types with no validators, [#926](https://github.com/pydantic/pydantic/issues/926) by [@retnikt](https://github.com/retnikt) + +## v1.0b2 (2019-10-07) + +* Mark `StrictBool` typecheck as `bool` to allow for default values without mypy errors, [#690](https://github.com/pydantic/pydantic/issues/690) by [@dmontagu](https://github.com/dmontagu) +* Transfer the documentation build from sphinx to mkdocs, re-write much of the documentation, [#856](https://github.com/pydantic/pydantic/issues/856) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for custom naming schemes for `GenericModel` subclasses, [#859](https://github.com/pydantic/pydantic/issues/859) by [@dmontagu](https://github.com/dmontagu) +* Add `if TYPE_CHECKING:` to the excluded lines for test coverage, [#874](https://github.com/pydantic/pydantic/issues/874) by [@dmontagu](https://github.com/dmontagu) +* Rename `allow_population_by_alias` to `allow_population_by_field_name`, remove unnecessary warning about it, [#875](https://github.com/pydantic/pydantic/issues/875) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.0b1 (2019-10-01) + +* **Breaking Change:** rename `Schema` to `Field`, make it a function to placate mypy, [#577](https://github.com/pydantic/pydantic/issues/577) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** modify parsing behavior for `bool`, [#617](https://github.com/pydantic/pydantic/issues/617) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** `get_validators` is no longer recognised, use `__get_validators__`. + `Config.ignore_extra` and `Config.allow_extra` are no longer recognised, use `Config.extra`, [#720](https://github.com/pydantic/pydantic/issues/720) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** modify default config settings for `BaseSettings`; `case_insensitive` renamed to `case_sensitive`, + default changed to `case_sensitive = False`, `env_prefix` default changed to `''` - e.g. no prefix, [#721](https://github.com/pydantic/pydantic/issues/721) by [@dmontagu](https://github.com/dmontagu) +* **Breaking change:** Implement `root_validator` and rename root errors from `__obj__` to `__root__`, [#729](https://github.com/pydantic/pydantic/issues/729) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** alter the behaviour of `dict(model)` so that sub-models are nolonger + converted to dictionaries, [#733](https://github.com/pydantic/pydantic/issues/733) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking change:** Added `initvars` support to `post_init_post_parse`, [#748](https://github.com/pydantic/pydantic/issues/748) by [@Raphael-C-Almeida](https://github.com/Raphael-C-Almeida) +* **Breaking Change:** Make `BaseModel.json()` only serialize the `__root__` key for models with custom root, [#752](https://github.com/pydantic/pydantic/issues/752) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** complete rewrite of `URL` parsing logic, [#755](https://github.com/pydantic/pydantic/issues/755) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** preserve superclass annotations for field-determination when not provided in subclass, [#757](https://github.com/pydantic/pydantic/issues/757) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** `BaseSettings` now uses the special `env` settings to define which environment variables to + read, not aliases, [#847](https://github.com/pydantic/pydantic/issues/847) by [@samuelcolvin](https://github.com/samuelcolvin) +* add support for `assert` statements inside validators, [#653](https://github.com/pydantic/pydantic/issues/653) by [@abdusco](https://github.com/abdusco) +* Update documentation to specify the use of `pydantic.dataclasses.dataclass` and subclassing `pydantic.BaseModel`, [#710](https://github.com/pydantic/pydantic/issues/710) by [@maddosaurus](https://github.com/maddosaurus) +* Allow custom JSON decoding and encoding via `json_loads` and `json_dumps` `Config` properties, [#714](https://github.com/pydantic/pydantic/issues/714) by [@samuelcolvin](https://github.com/samuelcolvin) +* make all annotated fields occur in the order declared, [#715](https://github.com/pydantic/pydantic/issues/715) by [@dmontagu](https://github.com/dmontagu) +* use pytest to test `mypy` integration, [#735](https://github.com/pydantic/pydantic/issues/735) by [@dmontagu](https://github.com/dmontagu) +* add `__repr__` method to `ErrorWrapper`, [#738](https://github.com/pydantic/pydantic/issues/738) by [@samuelcolvin](https://github.com/samuelcolvin) +* Added support for `FrozenSet` members in dataclasses, and a better error when attempting to use types from the `typing` module that are not supported by Pydantic, [#745](https://github.com/pydantic/pydantic/issues/745) by [@djpetti](https://github.com/djpetti) +* add documentation for Pycharm Plugin, [#750](https://github.com/pydantic/pydantic/issues/750) by [@koxudaxi](https://github.com/koxudaxi) +* fix broken examples in the docs, [#753](https://github.com/pydantic/pydantic/issues/753) by [@dmontagu](https://github.com/dmontagu) +* moving typing related objects into `pydantic.typing`, [#761](https://github.com/pydantic/pydantic/issues/761) by [@samuelcolvin](https://github.com/samuelcolvin) +* Minor performance improvements to `ErrorWrapper`, `ValidationError` and datetime parsing, [#763](https://github.com/pydantic/pydantic/issues/763) by [@samuelcolvin](https://github.com/samuelcolvin) +* Improvements to `datetime`/`date`/`time`/`timedelta` types: more descriptive errors, + change errors to `value_error` not `type_error`, support bytes, [#766](https://github.com/pydantic/pydantic/issues/766) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix error messages for `Literal` types with multiple allowed values, [#770](https://github.com/pydantic/pydantic/issues/770) by [@dmontagu](https://github.com/dmontagu) +* Improved auto-generated `title` field in JSON schema by converting underscore to space, [#772](https://github.com/pydantic/pydantic/issues/772) by [@skewty](https://github.com/skewty) +* support `mypy --no-implicit-reexport` for dataclasses, also respect `--no-implicit-reexport` in pydantic itself, [#783](https://github.com/pydantic/pydantic/issues/783) by [@samuelcolvin](https://github.com/samuelcolvin) +* add the `PaymentCardNumber` type, [#790](https://github.com/pydantic/pydantic/issues/790) by [@matin](https://github.com/matin) +* Fix const validations for lists, [#794](https://github.com/pydantic/pydantic/issues/794) by [@hmvp](https://github.com/hmvp) +* Set `additionalProperties` to false in schema for models with extra fields disallowed, [#796](https://github.com/pydantic/pydantic/issues/796) by [@Code0x58](https://github.com/Code0x58) +* `EmailStr` validation method now returns local part case-sensitive per RFC 5321, [#798](https://github.com/pydantic/pydantic/issues/798) by [@henriklindgren](https://github.com/henriklindgren) +* Added ability to validate strictness to `ConstrainedFloat`, `ConstrainedInt` and `ConstrainedStr` and added + `StrictFloat` and `StrictInt` classes, [#799](https://github.com/pydantic/pydantic/issues/799) by [@DerRidda](https://github.com/DerRidda) +* Improve handling of `None` and `Optional`, replace `whole` with `each_item` (inverse meaning, default `False`) + on validators, [#803](https://github.com/pydantic/pydantic/issues/803) by [@samuelcolvin](https://github.com/samuelcolvin) +* add support for `Type[T]` type hints, [#807](https://github.com/pydantic/pydantic/issues/807) by [@timonbimon](https://github.com/timonbimon) +* Performance improvements from removing `change_exceptions`, change how pydantic error are constructed, [#819](https://github.com/pydantic/pydantic/issues/819) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix the error message arising when a `BaseModel`-type model field causes a `ValidationError` during parsing, [#820](https://github.com/pydantic/pydantic/issues/820) by [@dmontagu](https://github.com/dmontagu) +* allow `getter_dict` on `Config`, modify `GetterDict` to be more like a `Mapping` object and thus easier to work with, [#821](https://github.com/pydantic/pydantic/issues/821) by [@samuelcolvin](https://github.com/samuelcolvin) +* Only check `TypeVar` param on base `GenericModel` class, [#842](https://github.com/pydantic/pydantic/issues/842) by [@zpencerq](https://github.com/zpencerq) +* rename `Model._schema_cache` -> `Model.__schema_cache__`, `Model._json_encoder` -> `Model.__json_encoder__`, + `Model._custom_root_type` -> `Model.__custom_root_type__`, [#851](https://github.com/pydantic/pydantic/issues/851) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.32.2 (2019-08-17) + +(Docs are available [here](https://5d584fcca7c9b70007d1c997--pydantic-docs.netlify.com)) + +* fix `__post_init__` usage with dataclass inheritance, fix [#739](https://github.com/pydantic/pydantic/issues/739) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix required fields validation on GenericModels classes, [#742](https://github.com/pydantic/pydantic/issues/742) by [@amitbl](https://github.com/amitbl) +* fix defining custom `Schema` on `GenericModel` fields, [#754](https://github.com/pydantic/pydantic/issues/754) by [@amitbl](https://github.com/amitbl) + +## v0.32.1 (2019-08-08) + +* do not validate extra fields when `validate_assignment` is on, [#724](https://github.com/pydantic/pydantic/issues/724) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) + +## v0.32 (2019-08-06) + +* add model name to `ValidationError` error message, [#676](https://github.com/pydantic/pydantic/issues/676) by [@dmontagu](https://github.com/dmontagu) +* **breaking change**: remove `__getattr__` and rename `__values__` to `__dict__` on `BaseModel`, + deprecation warning on use `__values__` attr, attributes access speed increased up to 14 times, [#712](https://github.com/pydantic/pydantic/issues/712) by [@Bobronium](https://github.com/Bobronium) +* support `ForwardRef` (without self-referencing annotations) in Python 3.6, [#706](https://github.com/pydantic/pydantic/issues/706) by [@koxudaxi](https://github.com/koxudaxi) +* implement `schema_extra` in `Config` sub-class, [#663](https://github.com/pydantic/pydantic/issues/663) by [@tiangolo](https://github.com/tiangolo) + +## v0.31.1 (2019-07-31) + +* fix json generation for `EnumError`, [#697](https://github.com/pydantic/pydantic/issues/697) by [@dmontagu](https://github.com/dmontagu) +* update numerous dependencies + +## v0.31 (2019-07-24) + +* better support for floating point `multiple_of` values, [#652](https://github.com/pydantic/pydantic/issues/652) by [@justindujardin](https://github.com/justindujardin) +* fix schema generation for `NewType` and `Literal`, [#649](https://github.com/pydantic/pydantic/issues/649) by [@dmontagu](https://github.com/dmontagu) +* fix `alias_generator` and field config conflict, [#645](https://github.com/pydantic/pydantic/issues/645) by [@gmetzker](https://github.com/gmetzker) and [#658](https://github.com/pydantic/pydantic/issues/658) by [@Bobronium](https://github.com/Bobronium) +* more detailed message for `EnumError`, [#673](https://github.com/pydantic/pydantic/issues/673) by [@dmontagu](https://github.com/dmontagu) +* add advanced exclude support for `dict`, `json` and `copy`, [#648](https://github.com/pydantic/pydantic/issues/648) by [@Bobronium](https://github.com/Bobronium) +* fix bug in `GenericModel` for models with concrete parameterized fields, [#672](https://github.com/pydantic/pydantic/issues/672) by [@dmontagu](https://github.com/dmontagu) +* add documentation for `Literal` type, [#651](https://github.com/pydantic/pydantic/issues/651) by [@dmontagu](https://github.com/dmontagu) +* add `Config.keep_untouched` for custom descriptors support, [#679](https://github.com/pydantic/pydantic/issues/679) by [@Bobronium](https://github.com/Bobronium) +* use `inspect.cleandoc` internally to get model description, [#657](https://github.com/pydantic/pydantic/issues/657) by [@tiangolo](https://github.com/tiangolo) +* add `Color` to schema generation, by [@euri10](https://github.com/euri10) +* add documentation for Literal type, [#651](https://github.com/pydantic/pydantic/issues/651) by [@dmontagu](https://github.com/dmontagu) + +## v0.30.1 (2019-07-15) + +* fix so nested classes which inherit and change `__init__` are correctly processed while still allowing `self` as a + parameter, [#644](https://github.com/pydantic/pydantic/issues/644) by [@lnaden](https://github.com/lnaden) and [@dgasmith](https://github.com/dgasmith) + +## v0.30 (2019-07-07) + +* enforce single quotes in code, [#612](https://github.com/pydantic/pydantic/issues/612) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix infinite recursion with dataclass inheritance and `__post_init__`, [#606](https://github.com/pydantic/pydantic/issues/606) by [@Hanaasagi](https://github.com/Hanaasagi) +* fix default values for `GenericModel`, [#610](https://github.com/pydantic/pydantic/issues/610) by [@dmontagu](https://github.com/dmontagu) +* clarify that self-referencing models require Python 3.7+, [#616](https://github.com/pydantic/pydantic/issues/616) by [@vlcinsky](https://github.com/vlcinsky) +* fix truncate for types, [#611](https://github.com/pydantic/pydantic/issues/611) by [@dmontagu](https://github.com/dmontagu) +* add `alias_generator` support, [#622](https://github.com/pydantic/pydantic/issues/622) by [@Bobronium](https://github.com/Bobronium) +* fix unparameterized generic type schema generation, [#625](https://github.com/pydantic/pydantic/issues/625) by [@dmontagu](https://github.com/dmontagu) +* fix schema generation with multiple/circular references to the same model, [#621](https://github.com/pydantic/pydantic/issues/621) by [@tiangolo](https://github.com/tiangolo) and [@wongpat](https://github.com/wongpat) +* support custom root types, [#628](https://github.com/pydantic/pydantic/issues/628) by [@koxudaxi](https://github.com/koxudaxi) +* support `self` as a field name in `parse_obj`, [#632](https://github.com/pydantic/pydantic/issues/632) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.29 (2019-06-19) + +* support dataclasses.InitVar, [#592](https://github.com/pydantic/pydantic/issues/592) by [@pfrederiks](https://github.com/pfrederiks) +* Updated documentation to elucidate the usage of `Union` when defining multiple types under an attribute's + annotation and showcase how the type-order can affect marshalling of provided values, [#594](https://github.com/pydantic/pydantic/issues/594) by [@somada141](https://github.com/somada141) +* add `conlist` type, [#583](https://github.com/pydantic/pydantic/issues/583) by [@hmvp](https://github.com/hmvp) +* add support for generics, [#595](https://github.com/pydantic/pydantic/issues/595) by [@dmontagu](https://github.com/dmontagu) + +## v0.28 (2019-06-06) + +* fix support for JSON Schema generation when using models with circular references in Python 3.7, [#572](https://github.com/pydantic/pydantic/issues/572) by [@tiangolo](https://github.com/tiangolo) +* support `__post_init_post_parse__` on dataclasses, [#567](https://github.com/pydantic/pydantic/issues/567) by [@sevaho](https://github.com/sevaho) +* allow dumping dataclasses to JSON, [#575](https://github.com/pydantic/pydantic/issues/575) by [@samuelcolvin](https://github.com/samuelcolvin) and [@DanielOberg](https://github.com/DanielOberg) +* ORM mode, [#562](https://github.com/pydantic/pydantic/issues/562) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix `pydantic.compiled` on ipython, [#573](https://github.com/pydantic/pydantic/issues/573) by [@dmontagu](https://github.com/dmontagu) and [@samuelcolvin](https://github.com/samuelcolvin) +* add `StrictBool` type, [#579](https://github.com/pydantic/pydantic/issues/579) by [@cazgp](https://github.com/cazgp) + +## v0.27 (2019-05-30) + +* **breaking change** `_pydantic_post_init` to execute dataclass' original `__post_init__` before + validation, [#560](https://github.com/pydantic/pydantic/issues/560) by [@HeavenVolkoff](https://github.com/HeavenVolkoff) +* fix handling of generic types without specified parameters, [#550](https://github.com/pydantic/pydantic/issues/550) by [@dmontagu](https://github.com/dmontagu) +* **breaking change** (maybe): this is the first release compiled with **cython**, see the docs and please + submit an issue if you run into problems + +## v0.27.0a1 (2019-05-26) + +* fix JSON Schema for `list`, `tuple`, and `set`, [#540](https://github.com/pydantic/pydantic/issues/540) by [@tiangolo](https://github.com/tiangolo) +* compiling with cython, `manylinux` binaries, some other performance improvements, [#548](https://github.com/pydantic/pydantic/issues/548) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.26 (2019-05-22) + +* fix to schema generation for `IPvAnyAddress`, `IPvAnyInterface`, `IPvAnyNetwork` [#498](https://github.com/pydantic/pydantic/issues/498) by [@pilosus](https://github.com/pilosus) +* fix variable length tuples support, [#495](https://github.com/pydantic/pydantic/issues/495) by [@pilosus](https://github.com/pilosus) +* fix return type hint for `create_model`, [#526](https://github.com/pydantic/pydantic/issues/526) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** fix `.dict(skip_keys=True)` skipping values set via alias (this involves changing + `validate_model()` to always returns `Tuple[Dict[str, Any], Set[str], Optional[ValidationError]]`), [#517](https://github.com/pydantic/pydantic/issues/517) by [@sommd](https://github.com/sommd) +* fix to schema generation for `IPv4Address`, `IPv6Address`, `IPv4Interface`, + `IPv6Interface`, `IPv4Network`, `IPv6Network` [#532](https://github.com/pydantic/pydantic/issues/532) by [@euri10](https://github.com/euri10) +* add `Color` type, [#504](https://github.com/pydantic/pydantic/issues/504) by [@pilosus](https://github.com/pilosus) and [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.25 (2019-05-05) + +* Improve documentation on self-referencing models and annotations, [#487](https://github.com/pydantic/pydantic/issues/487) by [@theenglishway](https://github.com/theenglishway) +* fix `.dict()` with extra keys, [#490](https://github.com/pydantic/pydantic/issues/490) by [@JaewonKim](https://github.com/JaewonKim) +* support `const` keyword in `Schema`, [#434](https://github.com/pydantic/pydantic/issues/434) by [@Sean1708](https://github.com/Sean1708) + +## v0.24 (2019-04-23) + +* fix handling `ForwardRef` in sub-types, like `Union`, [#464](https://github.com/pydantic/pydantic/issues/464) by [@tiangolo](https://github.com/tiangolo) +* fix secret serialization, [#465](https://github.com/pydantic/pydantic/issues/465) by [@atheuz](https://github.com/atheuz) +* Support custom validators for dataclasses, [#454](https://github.com/pydantic/pydantic/issues/454) by [@primal100](https://github.com/primal100) +* fix `parse_obj` to cope with dict-like objects, [#472](https://github.com/pydantic/pydantic/issues/472) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix to schema generation in nested dataclass-based models, [#474](https://github.com/pydantic/pydantic/issues/474) by [@NoAnyLove](https://github.com/NoAnyLove) +* fix `json` for `Path`, `FilePath`, and `DirectoryPath` objects, [#473](https://github.com/pydantic/pydantic/issues/473) by [@mikegoodspeed](https://github.com/mikegoodspeed) + +## v0.23 (2019-04-04) + +* improve documentation for contributing section, [#441](https://github.com/pydantic/pydantic/issues/441) by [@pilosus](https://github.com/pilosus) +* improve README.rst to include essential information about the package, [#446](https://github.com/pydantic/pydantic/issues/446) by [@pilosus](https://github.com/pilosus) +* `IntEnum` support, [#444](https://github.com/pydantic/pydantic/issues/444) by [@potykion](https://github.com/potykion) +* fix PyObject callable value, [#409](https://github.com/pydantic/pydantic/issues/409) by [@pilosus](https://github.com/pilosus) +* fix `black` deprecation warnings after update, [#451](https://github.com/pydantic/pydantic/issues/451) by [@pilosus](https://github.com/pilosus) +* fix `ForwardRef` collection bug, [#450](https://github.com/pydantic/pydantic/issues/450) by [@tigerwings](https://github.com/tigerwings) +* Support specialized `ClassVars`, [#455](https://github.com/pydantic/pydantic/issues/455) by [@tyrylu](https://github.com/tyrylu) +* fix JSON serialization for `ipaddress` types, [#333](https://github.com/pydantic/pydantic/issues/333) by [@pilosus](https://github.com/pilosus) +* add `SecretStr` and `SecretBytes` types, [#452](https://github.com/pydantic/pydantic/issues/452) by [@atheuz](https://github.com/atheuz) + +## v0.22 (2019-03-29) + +* add `IPv{4,6,Any}Network` and `IPv{4,6,Any}Interface` types from `ipaddress` stdlib, [#333](https://github.com/pydantic/pydantic/issues/333) by [@pilosus](https://github.com/pilosus) +* add docs for `datetime` types, [#386](https://github.com/pydantic/pydantic/issues/386) by [@pilosus](https://github.com/pilosus) +* fix to schema generation in dataclass-based models, [#408](https://github.com/pydantic/pydantic/issues/408) by [@pilosus](https://github.com/pilosus) +* fix path in nested models, [#437](https://github.com/pydantic/pydantic/issues/437) by [@kataev](https://github.com/kataev) +* add `Sequence` support, [#304](https://github.com/pydantic/pydantic/issues/304) by [@pilosus](https://github.com/pilosus) + +## v0.21.0 (2019-03-15) + +* fix typo in `NoneIsNotAllowedError` message, [#414](https://github.com/pydantic/pydantic/issues/414) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) +* add `IPvAnyAddress`, `IPv4Address` and `IPv6Address` types, [#333](https://github.com/pydantic/pydantic/issues/333) by [@pilosus](https://github.com/pilosus) + +## v0.20.1 (2019-02-26) + +* fix type hints of `parse_obj` and similar methods, [#405](https://github.com/pydantic/pydantic/issues/405) by [@erosennin](https://github.com/erosennin) +* fix submodel validation, [#403](https://github.com/pydantic/pydantic/issues/403) by [@samuelcolvin](https://github.com/samuelcolvin) +* correct type hints for `ValidationError.json`, [#406](https://github.com/pydantic/pydantic/issues/406) by [@layday](https://github.com/layday) + +## v0.20.0 (2019-02-18) + +* fix tests for Python 3.8, [#396](https://github.com/pydantic/pydantic/issues/396) by [@samuelcolvin](https://github.com/samuelcolvin) +* Adds fields to the `dir` method for autocompletion in interactive sessions, [#398](https://github.com/pydantic/pydantic/issues/398) by [@dgasmith](https://github.com/dgasmith) +* support `ForwardRef` (and therefore `from __future__ import annotations`) with dataclasses, [#397](https://github.com/pydantic/pydantic/issues/397) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.20.0a1 (2019-02-13) + +* **breaking change** (maybe): more sophisticated argument parsing for validators, any subset of + `values`, `config` and `field` is now permitted, eg. `(cls, value, field)`, + however the variadic key word argument ("`**kwargs`") **must** be called `kwargs`, [#388](https://github.com/pydantic/pydantic/issues/388) by [@samuelcolvin](https://github.com/samuelcolvin) +* **breaking change**: Adds `skip_defaults` argument to `BaseModel.dict()` to allow skipping of fields that + were not explicitly set, signature of `Model.construct()` changed, [#389](https://github.com/pydantic/pydantic/issues/389) by [@dgasmith](https://github.com/dgasmith) +* add `py.typed` marker file for PEP-561 support, [#391](https://github.com/pydantic/pydantic/issues/391) by [@je-l](https://github.com/je-l) +* Fix `extra` behaviour for multiple inheritance/mix-ins, [#394](https://github.com/pydantic/pydantic/issues/394) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) + +## v0.19.0 (2019-02-04) + +* Support `Callable` type hint, fix [#279](https://github.com/pydantic/pydantic/issues/279) by [@proofit404](https://github.com/proofit404) +* Fix schema for fields with `validator` decorator, fix [#375](https://github.com/pydantic/pydantic/issues/375) by [@tiangolo](https://github.com/tiangolo) +* Add `multiple_of` constraint to `ConstrainedDecimal`, `ConstrainedFloat`, `ConstrainedInt` + and their related types `condecimal`, `confloat`, and `conint` [#371](https://github.com/pydantic/pydantic/issues/371), thanks [@StephenBrown2](https://github.com/StephenBrown2) +* Deprecated `ignore_extra` and `allow_extra` Config fields in favor of `extra`, [#352](https://github.com/pydantic/pydantic/issues/352) by [@liiight](https://github.com/liiight) +* Add type annotations to all functions, test fully with mypy, [#373](https://github.com/pydantic/pydantic/issues/373) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix for 'missing' error with `validate_all` or `validate_always`, [#381](https://github.com/pydantic/pydantic/issues/381) by [@samuelcolvin](https://github.com/samuelcolvin) +* Change the second/millisecond watershed for date/datetime parsing to `2e10`, [#385](https://github.com/pydantic/pydantic/issues/385) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.18.2 (2019-01-22) + +* Fix to schema generation with `Optional` fields, fix [#361](https://github.com/pydantic/pydantic/issues/361) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.18.1 (2019-01-17) + +* add `ConstrainedBytes` and `conbytes` types, [#315](https://github.com/pydantic/pydantic/issues/315) [@Gr1N](https://github.com/Gr1N) +* adding `MANIFEST.in` to include license in package `.tar.gz`, [#358](https://github.com/pydantic/pydantic/issues/358) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.18.0 (2019-01-13) + +* **breaking change**: don't call validators on keys of dictionaries, [#254](https://github.com/pydantic/pydantic/issues/254) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix validators with `always=True` when the default is `None` or the type is optional, also prevent + `whole` validators being called for sub-fields, fix [#132](https://github.com/pydantic/pydantic/issues/132) by [@samuelcolvin](https://github.com/samuelcolvin) +* improve documentation for settings priority and allow it to be easily changed, [#343](https://github.com/pydantic/pydantic/issues/343) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix `ignore_extra=False` and `allow_population_by_alias=True`, fix [#257](https://github.com/pydantic/pydantic/issues/257) by [@samuelcolvin](https://github.com/samuelcolvin) +* **breaking change**: Set `BaseConfig` attributes `min_anystr_length` and `max_anystr_length` to + `None` by default, fix [#349](https://github.com/pydantic/pydantic/issues/349) in [#350](https://github.com/pydantic/pydantic/issues/350) by [@tiangolo](https://github.com/tiangolo) +* add support for postponed annotations, [#348](https://github.com/pydantic/pydantic/issues/348) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.17.0 (2018-12-27) + +* fix schema for `timedelta` as number, [#325](https://github.com/pydantic/pydantic/issues/325) by [@tiangolo](https://github.com/tiangolo) +* prevent validators being called repeatedly after inheritance, [#327](https://github.com/pydantic/pydantic/issues/327) by [@samuelcolvin](https://github.com/samuelcolvin) +* prevent duplicate validator check in ipython, fix [#312](https://github.com/pydantic/pydantic/issues/312) by [@samuelcolvin](https://github.com/samuelcolvin) +* add "Using Pydantic" section to docs, [#323](https://github.com/pydantic/pydantic/issues/323) by [@tiangolo](https://github.com/tiangolo) & [#326](https://github.com/pydantic/pydantic/issues/326) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix schema generation for fields annotated as `: dict`, `: list`, + `: tuple` and `: set`, [#330](https://github.com/pydantic/pydantic/issues/330) & [#335](https://github.com/pydantic/pydantic/issues/335) by [@nkonin](https://github.com/nkonin) +* add support for constrained strings as dict keys in schema, [#332](https://github.com/pydantic/pydantic/issues/332) by [@tiangolo](https://github.com/tiangolo) +* support for passing Config class in dataclasses decorator, [#276](https://github.com/pydantic/pydantic/issues/276) by [@jarekkar](https://github.com/jarekkar) + (**breaking change**: this supersedes the `validate_assignment` argument with `config`) +* support for nested dataclasses, [#334](https://github.com/pydantic/pydantic/issues/334) by [@samuelcolvin](https://github.com/samuelcolvin) +* better errors when getting an `ImportError` with `PyObject`, [#309](https://github.com/pydantic/pydantic/issues/309) by [@samuelcolvin](https://github.com/samuelcolvin) +* rename `get_validators` to `__get_validators__`, deprecation warning on use of old name, [#338](https://github.com/pydantic/pydantic/issues/338) by [@samuelcolvin](https://github.com/samuelcolvin) +* support `ClassVar` by excluding such attributes from fields, [#184](https://github.com/pydantic/pydantic/issues/184) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.16.1 (2018-12-10) + +* fix `create_model` to correctly use the passed `__config__`, [#320](https://github.com/pydantic/pydantic/issues/320) by [@hugoduncan](https://github.com/hugoduncan) + +## v0.16.0 (2018-12-03) + +* **breaking change**: refactor schema generation to be compatible with JSON Schema and OpenAPI specs, [#308](https://github.com/pydantic/pydantic/issues/308) by [@tiangolo](https://github.com/tiangolo) +* add `schema` to `schema` module to generate top-level schemas from base models, [#308](https://github.com/pydantic/pydantic/issues/308) by [@tiangolo](https://github.com/tiangolo) +* add additional fields to `Schema` class to declare validation for `str` and numeric values, [#311](https://github.com/pydantic/pydantic/issues/311) by [@tiangolo](https://github.com/tiangolo) +* rename `_schema` to `schema` on fields, [#318](https://github.com/pydantic/pydantic/issues/318) by [@samuelcolvin](https://github.com/samuelcolvin) +* add `case_insensitive` option to `BaseSettings` `Config`, [#277](https://github.com/pydantic/pydantic/issues/277) by [@jasonkuhrt](https://github.com/jasonkuhrt) + +## v0.15.0 (2018-11-18) + +* move codebase to use black, [#287](https://github.com/pydantic/pydantic/issues/287) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix alias use in settings, [#286](https://github.com/pydantic/pydantic/issues/286) by [@jasonkuhrt](https://github.com/jasonkuhrt) and [@samuelcolvin](https://github.com/samuelcolvin) +* fix datetime parsing in `parse_date`, [#298](https://github.com/pydantic/pydantic/issues/298) by [@samuelcolvin](https://github.com/samuelcolvin) +* allow dataclass inheritance, fix [#293](https://github.com/pydantic/pydantic/issues/293) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix `PyObject = None`, fix [#305](https://github.com/pydantic/pydantic/issues/305) by [@samuelcolvin](https://github.com/samuelcolvin) +* allow `Pattern` type, fix [#303](https://github.com/pydantic/pydantic/issues/303) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.14.0 (2018-10-02) + +* dataclasses decorator, [#269](https://github.com/pydantic/pydantic/issues/269) by [@Gaunt](https://github.com/Gaunt) and [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.13.1 (2018-09-21) + +* fix issue where int_validator doesn't cast a `bool` to an `int` [#264](https://github.com/pydantic/pydantic/issues/264) by [@nphyatt](https://github.com/nphyatt) +* add deep copy support for `BaseModel.copy()` [#249](https://github.com/pydantic/pydantic/issues/249), [@gangefors](https://github.com/gangefors) + +## v0.13.0 (2018-08-25) + +* raise an exception if a field's name shadows an existing `BaseModel` attribute [#242](https://github.com/pydantic/pydantic/issues/242) +* add `UrlStr` and `urlstr` types [#236](https://github.com/pydantic/pydantic/issues/236) +* timedelta json encoding ISO8601 and total seconds, custom json encoders [#247](https://github.com/pydantic/pydantic/issues/247), by [@cfkanesan](https://github.com/cfkanesan) and [@samuelcolvin](https://github.com/samuelcolvin) +* allow `timedelta` objects as values for properties of type `timedelta` (matches `datetime` etc. behavior) [#247](https://github.com/pydantic/pydantic/issues/247) + +## v0.12.1 (2018-07-31) + +* fix schema generation for fields defined using `typing.Any` [#237](https://github.com/pydantic/pydantic/issues/237) + +## v0.12.0 (2018-07-31) + +* add `by_alias` argument in `.dict()` and `.json()` model methods [#205](https://github.com/pydantic/pydantic/issues/205) +* add Json type support [#214](https://github.com/pydantic/pydantic/issues/214) +* support tuples [#227](https://github.com/pydantic/pydantic/issues/227) +* major improvements and changes to schema [#213](https://github.com/pydantic/pydantic/issues/213) + +## v0.11.2 (2018-07-05) + +* add `NewType` support [#115](https://github.com/pydantic/pydantic/issues/115) +* fix `list`, `set` & `tuple` validation [#225](https://github.com/pydantic/pydantic/issues/225) +* separate out `validate_model` method, allow errors to be returned along with valid values [#221](https://github.com/pydantic/pydantic/issues/221) + +## v0.11.1 (2018-07-02) + +* support Python 3.7 [#216](https://github.com/pydantic/pydantic/issues/216), thanks [@layday](https://github.com/layday) +* Allow arbitrary types in model [#209](https://github.com/pydantic/pydantic/issues/209), thanks [@oldPadavan](https://github.com/oldPadavan) + +## v0.11.0 (2018-06-28) + +* make `list`, `tuple` and `set` types stricter [#86](https://github.com/pydantic/pydantic/issues/86) +* **breaking change**: remove msgpack parsing [#201](https://github.com/pydantic/pydantic/issues/201) +* add `FilePath` and `DirectoryPath` types [#10](https://github.com/pydantic/pydantic/issues/10) +* model schema generation [#190](https://github.com/pydantic/pydantic/issues/190) +* JSON serialisation of models and schemas [#133](https://github.com/pydantic/pydantic/issues/133) + +## v0.10.0 (2018-06-11) + +* add `Config.allow_population_by_alias` [#160](https://github.com/pydantic/pydantic/issues/160), thanks [@bendemaree](https://github.com/bendemaree) +* **breaking change**: new errors format [#179](https://github.com/pydantic/pydantic/issues/179), thanks [@Gr1N](https://github.com/Gr1N) +* **breaking change**: removed `Config.min_number_size` and `Config.max_number_size` [#183](https://github.com/pydantic/pydantic/issues/183), thanks [@Gr1N](https://github.com/Gr1N) +* **breaking change**: correct behaviour of `lt` and `gt` arguments to `conint` etc. [#188](https://github.com/pydantic/pydantic/issues/188) + for the old behaviour use `le` and `ge` [#194](https://github.com/pydantic/pydantic/issues/194), thanks [@jaheba](https://github.com/jaheba) +* added error context and ability to redefine error message templates using `Config.error_msg_templates` [#183](https://github.com/pydantic/pydantic/issues/183), + thanks [@Gr1N](https://github.com/Gr1N) +* fix typo in validator exception [#150](https://github.com/pydantic/pydantic/issues/150) +* copy defaults to model values, so different models don't share objects [#154](https://github.com/pydantic/pydantic/issues/154) + +## v0.9.1 (2018-05-10) + +* allow custom `get_field_config` on config classes [#159](https://github.com/pydantic/pydantic/issues/159) +* add `UUID1`, `UUID3`, `UUID4` and `UUID5` types [#167](https://github.com/pydantic/pydantic/issues/167), thanks [@Gr1N](https://github.com/Gr1N) +* modify some inconsistent docstrings and annotations [#173](https://github.com/pydantic/pydantic/issues/173), thanks [@YannLuo](https://github.com/YannLuo) +* fix type annotations for exotic types [#171](https://github.com/pydantic/pydantic/issues/171), thanks [@Gr1N](https://github.com/Gr1N) +* re-use type validators in exotic types [#171](https://github.com/pydantic/pydantic/issues/171) +* scheduled monthly requirements updates [#168](https://github.com/pydantic/pydantic/issues/168) +* add `Decimal`, `ConstrainedDecimal` and `condecimal` types [#170](https://github.com/pydantic/pydantic/issues/170), thanks [@Gr1N](https://github.com/Gr1N) + +## v0.9.0 (2018-04-28) + +* tweak email-validator import error message [#145](https://github.com/pydantic/pydantic/issues/145) +* fix parse error of `parse_date()` and `parse_datetime()` when input is 0 [#144](https://github.com/pydantic/pydantic/issues/144), thanks [@YannLuo](https://github.com/YannLuo) +* add `Config.anystr_strip_whitespace` and `strip_whitespace` kwarg to `constr`, + by default values is `False` [#163](https://github.com/pydantic/pydantic/issues/163), thanks [@Gr1N](https://github.com/Gr1N) +* add `ConstrainedFloat`, `confloat`, `PositiveFloat` and `NegativeFloat` types [#166](https://github.com/pydantic/pydantic/issues/166), thanks [@Gr1N](https://github.com/Gr1N) + +## v0.8.0 (2018-03-25) + +* fix type annotation for `inherit_config` [#139](https://github.com/pydantic/pydantic/issues/139) +* **breaking change**: check for invalid field names in validators [#140](https://github.com/pydantic/pydantic/issues/140) +* validate attributes of parent models [#141](https://github.com/pydantic/pydantic/issues/141) +* **breaking change**: email validation now uses + [email-validator](https://github.com/JoshData/python-email-validator) [#142](https://github.com/pydantic/pydantic/issues/142) + +## v0.7.1 (2018-02-07) + +* fix bug with `create_model` modifying the base class + +## v0.7.0 (2018-02-06) + +* added compatibility with abstract base classes (ABCs) [#123](https://github.com/pydantic/pydantic/issues/123) +* add `create_model` method [#113](https://github.com/pydantic/pydantic/issues/113) [#125](https://github.com/pydantic/pydantic/issues/125) +* **breaking change**: rename `.config` to `.__config__` on a model +* **breaking change**: remove deprecated `.values()` on a model, use `.dict()` instead +* remove use of `OrderedDict` and use simple dict [#126](https://github.com/pydantic/pydantic/issues/126) +* add `Config.use_enum_values` [#127](https://github.com/pydantic/pydantic/issues/127) +* add wildcard validators of the form `@validate('*')` [#128](https://github.com/pydantic/pydantic/issues/128) + +## v0.6.4 (2018-02-01) + +* allow Python date and times objects [#122](https://github.com/pydantic/pydantic/issues/122) + +## v0.6.3 (2017-11-26) + +* fix direct install without `README.rst` present + +## v0.6.2 (2017-11-13) + +* errors for invalid validator use +* safer check for complex models in `Settings` + +## v0.6.1 (2017-11-08) + +* prevent duplicate validators, [#101](https://github.com/pydantic/pydantic/issues/101) +* add `always` kwarg to validators, [#102](https://github.com/pydantic/pydantic/issues/102) + +## v0.6.0 (2017-11-07) + +* assignment validation [#94](https://github.com/pydantic/pydantic/issues/94), thanks petroswork! +* JSON in environment variables for complex types, [#96](https://github.com/pydantic/pydantic/issues/96) +* add `validator` decorators for complex validation, [#97](https://github.com/pydantic/pydantic/issues/97) +* depreciate `values(...)` and replace with `.dict(...)`, [#99](https://github.com/pydantic/pydantic/issues/99) + +## v0.5.0 (2017-10-23) + +* add `UUID` validation [#89](https://github.com/pydantic/pydantic/issues/89) +* remove `index` and `track` from error object (json) if they're null [#90](https://github.com/pydantic/pydantic/issues/90) +* improve the error text when a list is provided rather than a dict [#90](https://github.com/pydantic/pydantic/issues/90) +* add benchmarks table to docs [#91](https://github.com/pydantic/pydantic/issues/91) + +## v0.4.0 (2017-07-08) + +* show length in string validation error +* fix aliases in config during inheritance [#55](https://github.com/pydantic/pydantic/issues/55) +* simplify error display +* use unicode ellipsis in `truncate` +* add `parse_obj`, `parse_raw` and `parse_file` helper functions [#58](https://github.com/pydantic/pydantic/issues/58) +* switch annotation only fields to come first in fields list not last + +## v0.3.0 (2017-06-21) + +* immutable models via `config.allow_mutation = False`, associated cleanup and performance improvement [#44](https://github.com/pydantic/pydantic/issues/44) +* immutable helper methods `construct()` and `copy()` [#53](https://github.com/pydantic/pydantic/issues/53) +* allow pickling of models [#53](https://github.com/pydantic/pydantic/issues/53) +* `setattr` is removed as `__setattr__` is now intelligent [#44](https://github.com/pydantic/pydantic/issues/44) +* `raise_exception` removed, Models now always raise exceptions [#44](https://github.com/pydantic/pydantic/issues/44) +* instance method validators removed +* django-restful-framework benchmarks added [#47](https://github.com/pydantic/pydantic/issues/47) +* fix inheritance bug [#49](https://github.com/pydantic/pydantic/issues/49) +* make str type stricter so list, dict etc are not coerced to strings. [#52](https://github.com/pydantic/pydantic/issues/52) +* add `StrictStr` which only always strings as input [#52](https://github.com/pydantic/pydantic/issues/52) + +## v0.2.1 (2017-06-07) + +* pypi and travis together messed up the deploy of `v0.2` this should fix it + +## v0.2.0 (2017-06-07) + +* **breaking change**: `values()` on a model is now a method not a property, + takes `include` and `exclude` arguments +* allow annotation only fields to support mypy +* add pretty `to_string(pretty=True)` method for models + +## v0.1.0 (2017-06-03) + +* add docs +* add history diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/RECORD new file mode 100644 index 00000000..841e903c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/RECORD @@ -0,0 +1,85 @@ +pydantic-1.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pydantic-1.10.1.dist-info/LICENSE,sha256=hTAP7jiruii5lyyjNd4zTlWK0rLDrk0xZOxd05vA63I,1148 +pydantic-1.10.1.dist-info/METADATA,sha256=aCaGBaEILP3YihwL6soTbNMDkzTINo81FDMOLRkqLcA,138610 +pydantic-1.10.1.dist-info/RECORD,, +pydantic-1.10.1.dist-info/WHEEL,sha256=-FqDJjo4HrkrIaThvtAYef2eEAn1_QvVe5nINCnUEbQ,101 +pydantic-1.10.1.dist-info/entry_points.txt,sha256=EquH5n3pilIXg-LLa1K4evpu5-6dnvxzi6vwvkoAMns,45 +pydantic-1.10.1.dist-info/top_level.txt,sha256=cmo_5n0F_YY5td5nPZBfdjBENkmGg_pE5ShWXYbXxTM,9 +pydantic/__init__.cp37-win_amd64.pyd,sha256=9EtGfi-DXFH5kHn0ZVxxmSn1SAPIwIBc6WAxMn1vh3k,34304 +pydantic/__init__.py,sha256=IMonwleOL8_ijc_z8hbBS2Zr1VbJ3wZKEHyZTk7jAqI,2902 +pydantic/__pycache__/__init__.cpython-37.pyc,, +pydantic/__pycache__/_hypothesis_plugin.cpython-37.pyc,, +pydantic/__pycache__/annotated_types.cpython-37.pyc,, +pydantic/__pycache__/class_validators.cpython-37.pyc,, +pydantic/__pycache__/color.cpython-37.pyc,, +pydantic/__pycache__/config.cpython-37.pyc,, +pydantic/__pycache__/dataclasses.cpython-37.pyc,, +pydantic/__pycache__/datetime_parse.cpython-37.pyc,, +pydantic/__pycache__/decorator.cpython-37.pyc,, +pydantic/__pycache__/env_settings.cpython-37.pyc,, +pydantic/__pycache__/error_wrappers.cpython-37.pyc,, +pydantic/__pycache__/errors.cpython-37.pyc,, +pydantic/__pycache__/fields.cpython-37.pyc,, +pydantic/__pycache__/generics.cpython-37.pyc,, +pydantic/__pycache__/json.cpython-37.pyc,, +pydantic/__pycache__/main.cpython-37.pyc,, +pydantic/__pycache__/mypy.cpython-37.pyc,, +pydantic/__pycache__/networks.cpython-37.pyc,, +pydantic/__pycache__/parse.cpython-37.pyc,, +pydantic/__pycache__/schema.cpython-37.pyc,, +pydantic/__pycache__/tools.cpython-37.pyc,, +pydantic/__pycache__/types.cpython-37.pyc,, +pydantic/__pycache__/typing.cpython-37.pyc,, +pydantic/__pycache__/utils.cpython-37.pyc,, +pydantic/__pycache__/validators.cpython-37.pyc,, +pydantic/__pycache__/version.cpython-37.pyc,, +pydantic/_hypothesis_plugin.cp37-win_amd64.pyd,sha256=AVm6P6jGU5f1VmYMDO3Ah3t4Pc_prUvZaPsN2JOcHJ4,154112 +pydantic/_hypothesis_plugin.py,sha256=FVkVK7E7KUxJ5lBfYEtBrVyzZGPIOhL6FI1y4Mgx6xQ,14982 +pydantic/annotated_types.cp37-win_amd64.pyd,sha256=Wirz_vRbxCkNeSkJyaN1dKKKYSRM1I2QtCqPn5peixg,67072 +pydantic/annotated_types.py,sha256=nX2rXe0W24YU_ZBOxfSq3v_gE_WkliUaBkNu_BP4K_I,3196 +pydantic/class_validators.cp37-win_amd64.pyd,sha256=BsFXV5YCuY7GEN7WzV_8C8EzMw1uwBY0jHqV8KSgocE,183296 +pydantic/class_validators.py,sha256=RzsbOgU6D5HlRtzWglGtci5lob8deQjZBCTbJ7W6Jvc,14173 +pydantic/color.cp37-win_amd64.pyd,sha256=I1OZsbmnyfTdg8XllBjeroHKhvuwSphbjoA_5D40gyI,224256 +pydantic/color.py,sha256=Dof59e3zmdlBJAGFEnm10RQW_jId655sL_ojIOUzQQ8,17305 +pydantic/config.cp37-win_amd64.pyd,sha256=S0Bu5TKL4GG50a84zxJ3JFs_Lmr8xobsk8wHRAGNDtY,79360 +pydantic/config.py,sha256=ftQ1PIX-x2C1i4I7nt8QANrc-uKebmVvaXBWZ5ODoSc,6682 +pydantic/dataclasses.cp37-win_amd64.pyd,sha256=_8pkOT9iK_BJxJzHZHd4_NeQSioDOlMBO2C6cKv1QQY,177152 +pydantic/dataclasses.py,sha256=7WrYzv-3cGTaUixG6sRT_8iiypcNjnyQM6Cnu9tbDZg,17175 +pydantic/datetime_parse.cp37-win_amd64.pyd,sha256=qS_u19--OLIFTvcd9KEty5DiqgG8ffkMOLdRshMRycQ,96256 +pydantic/datetime_parse.py,sha256=iOM3uNOwF9ReLjZTgtoUd5Qc2LqFBH51FUQ7-E61Wk4,7962 +pydantic/decorator.cp37-win_amd64.pyd,sha256=0Qii4T9JcQsh8rlIuhf_3i1IcwQe4PNlIoEDx59A1dU,134144 +pydantic/decorator.py,sha256=Yc9SUTzNgcOm_y481pqdtYsGs3vQQDAT77SMtp_A9rE,10527 +pydantic/env_settings.cp37-win_amd64.pyd,sha256=-sS38CRblnLuwL18FNidv8TPA6cLyKGvCa3NJmi0pUE,169472 +pydantic/env_settings.py,sha256=c0bnrFTcUEhKU3HZ7IYJzY9_97K7IQEyWkCiL2bPog8,14238 +pydantic/error_wrappers.cp37-win_amd64.pyd,sha256=TrVhyAsNQbmCXTJEhEVEkXJtuqYRoXfE_KIK2kuEuyU,117248 +pydantic/error_wrappers.py,sha256=ughxvoJSWSBHoQqTOiKIElrgCdTrKdfd4aXPbEUyufc,5304 +pydantic/errors.cp37-win_amd64.pyd,sha256=P11lPsK40fJTcV-14g2rQ0rNKB2_46yJpntmFAnzM7s,184320 +pydantic/errors.py,sha256=qpw1Ac9YcJOwPkkGl_ejt5k1L92YJLnQ7kKv33DvPHE,18339 +pydantic/fields.cp37-win_amd64.pyd,sha256=Gu8PLJGMyzHttbgwL_ljVxsyrbg0YDwF4qbQLxwBrgM,391168 +pydantic/fields.py,sha256=zNH8Ycr_5IXQCPlKylqBZQDfncN9z3hBVx4Toj2BFkA,51065 +pydantic/generics.py,sha256=k66LdBXhSPgKgE8LPVI-drKFmZvA7sCjSt3DxRGjGec,16355 +pydantic/json.cp37-win_amd64.pyd,sha256=y6JhxjxeG80ycepr3OcjvRGVPfLWr7Es3Ger8ZX3dF0,69632 +pydantic/json.py,sha256=oBUAWTZ9WHdpNPOVG9YFAo84RBJwLnJ1UZXprrKJ6pY,3458 +pydantic/main.cp37-win_amd64.pyd,sha256=_huKlo0DxuiThhdJooVBK_SPkaa1PPpBLKAHqteJiVU,385024 +pydantic/main.py,sha256=XhcB5wIK_4CAOg1uQjbtAMyMGfoOz-OWxw2CNSiCz_Q,45424 +pydantic/mypy.cp37-win_amd64.pyd,sha256=QLhAtuez3eR1yylExJUtnhO8Rxg_KpSrMwIf65vDu2Y,318464 +pydantic/mypy.py,sha256=uKv7WbD0YZ0jEbaBbsAmUh0dPUHQh2yF0XbEByaeDiI,34833 +pydantic/networks.cp37-win_amd64.pyd,sha256=lYLsG-uKvGztgGHg937AGbqe3OaJpQmgQs4iU-3YPNc,256512 +pydantic/networks.py,sha256=uCbTpO-rte3-22kZB4GG5pCJ6xBPdrcZlizkOQehvHU,22997 +pydantic/parse.cp37-win_amd64.pyd,sha256=RJ5SDKOrUMT5HgkgUiYUvrU4HN1oYdt9Gw_aAsfUNzE,50176 +pydantic/parse.py,sha256=LIo38lV-iaHWb1cWxryDHo79UQ7GUC2bHOwTPherYbM,1876 +pydantic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pydantic/schema.cp37-win_amd64.pyd,sha256=7qgvUK5zkiKUGWGmTxLL3aBGOAh1Lhn5tZ4PKlvU_uU,346624 +pydantic/schema.py,sha256=rLLcDLO-xLgY6376uqwfzk7f8MHkkcLg0imMP2IpF58,48299 +pydantic/tools.cp37-win_amd64.pyd,sha256=euNZ3DFXbly9W34X3PTs__BxYGk6BQkQaAhtYhHOx4w,64000 +pydantic/tools.py,sha256=QS5T9ySTA5AeS-OvZN0dMoODMMtDq4Rnef5y_11xQ28,2926 +pydantic/types.cp37-win_amd64.pyd,sha256=WHmeE79EXUy1GfgWyF_aXTlIKwOdiv0iqaKV_-MqXZM,354816 +pydantic/types.py,sha256=Nc40CFsSunzepVvqtS7GeuGQpQtR1lt7adsa5qEV-ZM,35935 +pydantic/typing.cp37-win_amd64.pyd,sha256=nK-a8UlWiuTJSZruMQDBd5MSEhzyx5tPMtx7s88kLZ0,200704 +pydantic/typing.py,sha256=z35TPZ61qD3REnI_n63WGJqf1XSl1AMZoozdyr6RNvs,19745 +pydantic/utils.cp37-win_amd64.pyd,sha256=Dsyof-WCL7BfKFJbh_SiPyp5tG8sBk5Rorczixq52WE,305152 +pydantic/utils.py,sha256=6uzru0XY9WqAQBtPiFQ5rBS3ciFFwB263tY0xoajSGk,27939 +pydantic/validators.cp37-win_amd64.pyd,sha256=L-CpvzoKeXi1nSoO15X00L30E_Qx-QA6u5mikxBQoUs,264704 +pydantic/validators.py,sha256=0mBiSyEXDdkKJmyE6JVV9js_6Sf9ZVQRcd4BGlu-Ltc,21813 +pydantic/version.cp37-win_amd64.pyd,sha256=qjuAk3r9x5ea7ynIKEoQRn3M2y0uadJqsIdnRkNATCU,53760 +pydantic/version.py,sha256=Nj1AXdUuCRdtXK6j_ZTjKlz_iTW1nAc0PLiPEJ21Khg,1076 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/WHEEL new file mode 100644 index 00000000..50364dcd --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: false +Tag: cp37-cp37m-win_amd64 + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/entry_points.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/entry_points.txt new file mode 100644 index 00000000..6178b39c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[hypothesis] +_ = pydantic._hypothesis_plugin diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/top_level.txt new file mode 100644 index 00000000..572b352f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic-1.10.1.dist-info/top_level.txt @@ -0,0 +1 @@ +pydantic diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/__init__.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/__init__.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..10f0e8bc55f2e63cbb8532de6f57edabaa09fa97 GIT binary patch literal 34304 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/__init__.py new file mode 100644 index 00000000..3bf1418f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/__init__.py @@ -0,0 +1,131 @@ +# flake8: noqa +from . import dataclasses +from .annotated_types import create_model_from_namedtuple, create_model_from_typeddict +from .class_validators import root_validator, validator +from .config import BaseConfig, ConfigDict, Extra +from .decorator import validate_arguments +from .env_settings import BaseSettings +from .error_wrappers import ValidationError +from .errors import * +from .fields import Field, PrivateAttr, Required +from .main import * +from .networks import * +from .parse import Protocol +from .tools import * +from .types import * +from .version import VERSION, compiled + +__version__ = VERSION + +# WARNING __all__ from .errors is not included here, it will be removed as an export here in v2 +# please use "from pydantic.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', +] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/_hypothesis_plugin.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/_hypothesis_plugin.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..bb8731712d78b8f2efad4073cab1561d077ac3dc GIT binary patch literal 154112 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/_hypothesis_plugin.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/_hypothesis_plugin.py new file mode 100644 index 00000000..a56d2b98 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/_hypothesis_plugin.py @@ -0,0 +1,386 @@ +""" +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://pydantic-docs.helpmanual.io/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.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. +# Once Cython can support 'normal' generics we'll revisit this. + +# 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()) + + +# 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/annotated_types.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/annotated_types.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..f0f60557daddeb5a5c34cd3410cba05af5485039 GIT binary patch literal 67072 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

p^S%FJNUmI)T!Snp++0;I8#kfl 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 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/class_validators.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/class_validators.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..b51adb2841427a8811468bb3c3bbbc22be6bc7a3 GIT binary patch literal 183296 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

I|=)Ac%Q{=P?G&juLu!dG7^%S*jIw& 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 F{|o6#tAPLj literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/class_validators.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/class_validators.py new file mode 100644 index 00000000..87190610 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/class_validators.py @@ -0,0 +1,342 @@ +import warnings +from collections import ChainMap +from functools import 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 .errors import ConfigError +from .typing import AnyCallable +from .utils import ROOT_KEY, in_ipython + +if TYPE_CHECKING: + from .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 .config import BaseConfig + from .fields import ModelField + from .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: 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 = f_cls.__func__.__module__ + '.' + f_cls.__func__.__qualname__ + 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 {v.func.__name__: v for v in validators} + else: + return None + + def check_for_unused(self) -> None: + unused_validators = set( + chain.from_iterable( + (v.func.__name__ 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 + + sig = signature(validator) + args = list(sig.parameters.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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/color.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/color.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..b716383f02bfd33fe1407bccab52313e19412bc9 GIT binary patch literal 224256 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/color.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/color.py new file mode 100644 index 00000000..6fdc9fb1 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/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 .errors import ColorError +from .utils import Representation, almost_equal_floats + +if TYPE_CHECKING: + from .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/config.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/config.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..58a31581ca18884c4f8356982a770d1816960b04 GIT binary patch literal 79360 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/config.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/config.py new file mode 100644 index 00000000..74687ca0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/config.py @@ -0,0 +1,192 @@ +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 .typing import AnyArgTCallable, AnyCallable +from .utils import GetterDict +from .version import compiled + +if TYPE_CHECKING: + from typing import overload + + from .fields import ModelField + from .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 +# Will be fixed with Cython 3 but still in alpha right now +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 + + # whether or not inherited models as fields should be reconstructed as base model + copy_on_model_validation: bool + # 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/dataclasses.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/dataclasses.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..1cb0f8300f63ddf8e1bdc5b5e208da6a2e06b785 GIT binary patch literal 177152 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

w! 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 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(kw_only_default=True, field_descriptors=(Field, FieldInfo)) + @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, + kw_only: bool = ..., + ) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']: + ... + + @dataclass_transform(kw_only_default=True, field_descriptors=(Field, FieldInfo)) + @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, + kw_only: bool = ..., + ) -> 'DataclassClassOrWrapper': + ... + +else: + + @dataclass_transform(kw_only_default=True, field_descriptors=(Field, FieldInfo)) + @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, + ) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']: + ... + + @dataclass_transform(kw_only_default=True, field_descriptors=(Field, FieldInfo)) + @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, + ) -> 'DataclassClassOrWrapper': + ... + + +@dataclass_transform(kw_only_default=True, field_descriptors=(Field, FieldInfo)) +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, + 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': + import dataclasses + + if is_builtin_dataclass(cls): + 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 __instancecheck__(self, instance: Any) -> bool: + return isinstance(instance, self.__dataclass__) + + +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__'): + 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` + import dataclasses + + # 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']: + import dataclasses + + 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 + + +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)} + else: + input_data = self.__dict__ + 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') + """ + import dataclasses + + 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, validate_on_init=False)) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/datetime_parse.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/datetime_parse.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..977183b06f3624df672b6b9e3a9f2d3c55fc7158 GIT binary patch literal 96256 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

9qR*>Lo<3ywtGC9YtpqwT&l= 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 cm+!CPZAI\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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/decorator.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/decorator.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..398881085bc0ea14f926a9e6da3e1bfd738c2d89 GIT binary patch literal 134144 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 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/env_settings.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/env_settings.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..acacb246bbb9ee6b89a1761072790ccfed281091 GIT binary patch literal 169472 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⋙zj-0@>rJOj3&UbC&ewX?OS>HU+On;fGk0`v@LUL+x zh5w&ElGT1T2RLv06!koP$jzax;n|jwd5>c$mwL~lI@nCw(`Ym!$3dcU0#x!EEY86; z%?BJEA&z2#-PbsZ9HQFg($0A3r~M^a+Ijkw@o3KT20rgEM_1;jFRHdBBA$Q~-eL07 zo>bj*H`_=J7O5qhNOid`{WJ zRQ43g0^D$pR7>a9I~CxRcU=zT;esqTULuFfwodG~@P4Z^aZ=hWu`lM)#2(TC(N?1_ z6T2Tzh<$>96W&b}_7AY&YKQWb%rk+8iqtA}jcPPcKuNQ^=l@{sfCviLyN0w2SjNUNO8)NkBRI1jyXVo@?I8qP?0gCUet+}glz0u}xHd3G?mr~v#sMfsAu#FJ5@8}=q*LLLniK0}SsqdOe#$kw@YV)=- zkD%I|#z&XbwAwG9;p0RiAri{)m-}zi70mN(?A!_rHc$|qs<5e<^V`lgPPcTLIRP|H zRrzeDyi0%zvc*=(aRTZLx>E8fhi-4sagUPWDrvY-)n+_U+&zBVwR9$?|1!C4!G#Lb z-=EwzR<~#K?5+~au_kX-RX3p-Z!^<*oZqPO``F7&HNU#^69`=FdUyXW|P}% zWFZkR|es3g37t5-I05(I{rab z!^qZE4QF(;i*$~*>!5mQ7x-^g4FlTNB!(>I@6xKc&!1H_2`)5aAM-T$ua5sv9sf9% z=(VUSF?<#0mq1F_6sb;*E7_?Y5OLRm70A`p>+!MaZ%p=L@kP~rTTeb)dWh96Y%N`X zQ>BOahrdpHz{)ghTT*`{NL1j0SbX!U@>eDw1x#DUQrgz;UKM|xb2zX?e7#}-=lsh~ zP@b-cVx(|rDiD{e)h&j?8@12rIyM&LRqeSVw(z$WRSlc2Y`n_2<0Tz~toO0_)+#Zv zilaWuf0=lq#UY1RGly36=XF3YWZv4>qrbo}TO z7UQ5@=_X+PS3swuz-E|W+#B`X8Nt0oO@bP$&cqtv?v_g=yghi%0biH~zcFx*&>v$B zXLfF@M4+R)DGqa0G2$QpAr^l(7Jp!x2(r*~imfar2m8nBYb-+u|nozI!GOR~s>M&jxsFX!WG09zd0*cM!|CmY_ zV8+DaQ`%O=zpIX)-LX2pAr?OtOpVOHLk*`H=)C3~o(AGJ9dVm-1`P18)68vJl`Uxe z7U!tDw0*PM6cFgufHsX9mleN`vb!RGrB0I8eOxWxoYJeyn`_H+;M* z<@tQd`1pG~nUBYpR3``lRq>J7{tPyyoZF)+{;2{%mIq7URMj&(ca#&CnycXNm94om zs628AxNsUGH#L_F1!2Ba!KPH~cO95GWD|dgboI1!RUSDX@Y+}`eni{&;I{FFb?XxS zrtzh=w_VRCDqUmo{;hvmSX#SjEPigs;1XORtgOciS4?h&PjWu#sr)<1`d)J2ij?=# zIHw1y#DJ<)OBCl$Xk8Uc4MIVj1~a}imTKWor6#z${_H-!aCjl~#PIT?VBs6H&Bx<= z)b63G-6Jee$_q391^yV;Z#2_37T@qoMO*xDQfuPT`%Q>)EXQ|^C19lER}Bw1;;uO2 zlk_@MUOfVAtUhZcM~ZkB-Ns_hnygTEVGzm=B$PE50YcdY7Rr9avt1~AU!km;$1s$Q zkkcf*VKr`>!q7%JY5VzS8%J*r(sqDw6thkW`i##6?L9=(jH2WXfxDTow73fV1Jr(7rOf(CRptP&~Af zG_E3lJD$LQ#`!d?A;cbAAf=7tuFDFbE7_sbk_Eo~Au+~27ZEZb(rAw2=hdh_$6B)0 zG)`iElmqJvM$?Z7TK}1ZNNYp*mEqQJV16TtGu-hr4@GDWTZ=RpdsW?R_Jw>$M56J)y}bdL5zh?(UVP!@2nDq8eAaD)8gL z;j=JVqbZc_{-@ox`+I7}JqhP4cJwN^LTB(q(2(1zpyOD$I02s5L~%$igr9SdKMFeG z`TfCm+f{Lr@iBK)HPsbWjFaA&8|H=-EWz4n{?9gmZ1`nCq8`4-xpdDzj;T!;9G`=v zkLa&C($#QBudK(Y*Z}L(;)+~}pFnjsxFafd4&MuU*vt@9+j#ChZrflgbX@D9v z<)dyUl|>B_Y2$-d90Nar>6Y%z`HjSaA&kwg=*!M%++EQdE_FuVt%+WR9`lkr(mc~q zW2<^K`ndxTgYA*QbAne;#h0PMU%|9|=zVl%n%ZDEwLS*zt6A*G3H8Dn&LLIowl4#a z|rbo@@OZFd(Hissif&|=#=n4H@7d>v(I2SQ?=ksY#PkfFKuPo>)9 zeKkNaoI|fOJ|6{@?_}G3DR7~0t1VCP%c&t_^vpe|HV>fg=;|Dt(R9AMOSb`z3EHo; z;@g;E%HSCkV-+eH`idkg|Jz<*#T=p5RWTG=;=)Ve;^w zjZ_iY$xz*JzU`4;ofB-L!P6c6P%XT~?GCC?ZWhOQMKmK$fN90EGTYVSs(33jjeeCg z;>XMhM)SF;czbvHyRhkmJXTFr~XCMdk84$7_-DEorf;Ts~ zBGvS*$G64RRU%^^%OL}K^mWXxg3+NobAKUOt6oi`B3b)4t}D8>|Kv66^Dx3Z<7ofAS`aoJls)Fj=REseIrmW!bL3}hvtHj?@Xe| zuVs1fGzA~T^m>O$Io*$Je-E{F50 zohBv14;EKPF{1yqmL_``(cie1Di{INZM!EzRFc6dJFBGTOQX7f5TYbb%9ZHQ6fj)g zk=Y2ls=ECa{6@1)1|VVq_=3pY0phpz6L=*SELw&bZU3Uc%7U&SikaVYBR!gcz;Pv^esBM z2c5L-{*ZV3V&gp2z@LjRNT zB}dnfX6^*1V6PD27;#14fZp47e-1fu`@Mv&A{IiA&ljqXy#?KrUH1^4NqG+)M)ed? zgWA1F4DXZ;9l&!E!$ZKN94LqyejZ9wiuer#>BmrL+r6DS7II7ZX{jq>8QLT>5vr`P zejlj9-kK<`R~FoifSuD)6F~|06GaqCAx~g|guadt;)m(6?1INmlkXAUAmcTV%+F#c zq#D?ETLGn7APBy~`b{u1JcH}mPGOJV5%IdZO4#ANzTw;OdxTdL{yys0yJFuui8=gF z0Eoa9T*s4Hp&gjg)BuDmW&VB=csJfFOhwQIcjAGn^;SZT{x6YDq>?vZh`(gv$}!=E zA!yr#gbZ4@eFn{6?NMEL*rTWa_KW0`&m^8);zF25{{D9>X7!lho7W9okxN~Xxx@Lc zh;10%yNc!|IckooyDcnn2$s0(s3X<*LWlJH>g-q0>EP_(eduuRi47r~>!JRM%SJW) z{M6+5UCs{Qk4T?Xh>Tv+YLz{@U$W&&x~9?VyyWZ)eTpY=`7aX}iG6bbm&m74kY;$= z%uD^|sOc^_@Iz;!o%q&6;|tsoM~*wqE%;`ELeNkKYW@NnE zr5#h-?rSB$vZUME_O6^GK&Kp`23NGJo&aFv=enbg0=(M@eesJ}u>{9@@XKrkp@pt^ zFV$aD(YO7NP<5{r}?W`~RJyv@LrS)|-V9^H)M3n>5fpxZEwP(N; zX>FmPMx?bKRvJk|P4~({0OjC)_tXIwZ?3oP83046M|()>#bjL#yiP1`-&&^}*+b^% zh(R+j;NYs!goL8fbR%&@DOicg@Dx`(i?b<5K7;L!AX4?u)Wd2br@5nmxCx!?)97Rn zXcgch%WyBp-em5dL2@M*o$q9X+i=HrSCq z+mhzj>IW{za|zgzIYw(ZF^pn{Ir(Khxv14 z0=-FDakM%Si^ZO@xmQw8=_efoNJ3xOS+EyEMDB?F!-uI$fO8dxL)W>Zd#MZ8g8JfG z8905Kbib*l8_Of;zZHpoh5kG2=Jka{=f%33?7a5!b%@_QX4d-9xu^tUhPN28?^1OZ zM?D2yulG!kXDxR=b0x&By2}Td| zQCtr%!FnO3i+C$gMY8N78k@*GMp{r9p=c;oCloCIT_|eo?bj&=G&0)VmJSd?&)Auu z7%6$k-OO|G-;z!^){b6sRUEhN{(&4VtRzpYbu6yTi9Q{D(RN3# zbjj~HyysapU7~1Xc(OF6eE@~U-HR=s;=~G-4UhGEoQ>5o5VN+xU2%1RZO?Lvo*b^# zMXrio3bdV!V?C(rJxrjmPn<%QRngw6=xW0m?RECXvhd&8H8=tPt14jE$+vr?6g{+i z83N=+C?8SF=y7tT#yvr64l7+wnT@{=m#wPbHSTAWeYML82P{0X%J$Gi+e2Byg}BY4 z+aFA{{UB@DS{0ob&8n*Cv+cQ;Y+u*=7TfOoa8+x&|8VRDC$-RFyW=rBi6<3Rd+JB9 zL+R35>WDQJ1L%u;4u?0^RGcK(J#U4tWnWI7N{!ne0-#dKusva_Fi<3rfuFI@(2f-N zOR4c{`2A@WCk81~X^?{(t-K*#_ zYON(g$wH4fL}WjVGzw@Kr81&m#<>n>N>Vb@#?&?hao%q44VM+5*~;JdGo zJYBZxfuVf>j~+|O8@>fQ7P0}6vvm=a_1P=_8jtS2brBTLHSTbHFuHy^u(*1EeU59= z!0_6XTVO`ugMv8!CDnR>UImN0?|@$3x;Wm|T^}Dl4?D&%uLclp=mF1Zgj$XfN`|t! zK8S~#;`WOO2YL=niG8!18s3Kp8Q!agd}Pmx+y9JQ8B6K5AEvlsG=CU1)kf(p^yqmn zu2ew|89oEI$U->CE=XVDdg#WD2qRrQ8)d@a&nul)2zVItqg4gaR#(NU0$UfU8(uI6 zgiBC6&F+T3i!xsW>hMf1bA-w)M;RA$xbUWMbZ%HL0me?N|A(h=n{f?GAFnByieoB{%>XSoU6IS%mCLXx6qymgU zNy1Yp?q}QcxI`ucAw%$eRLEW}?1TvzK(a$6V=6NC1Ls_aB8SgML$8rFqJ<8$5SkT^ z+y5O`ar*%NN+o(F)Chui{ejd16oKWBN)~rshU_(OP&;s15ZT{V+2_-?p9XR|vBG8l zk2eVop6*jm(YKBaPf7PH5>|37aU^+e9)I8CUmA^RI(x#CluYIDsa7zgMr=gQCe=5O z|FG)EXbQ_SZF9WqJy&=BJj7gZPEE2%@*XuL?KpYx=&M&3NgIrF+Y)Yoy0jm=PII~* zJ^;Ch?GvF$Z&Tn81Mvz2gS8Qwk1QJnbP(48{qE=r^mYhg?g~Y!c^e}fsq|2@BqC)w z9EkpDIpG768-WBg;MXvIPUvWj}d&(Ut)mA)sL+ZXZX?j#Rox56{-Y0qZZSkxSgL{*Q}nPoTEsiQ*3g=67-cbebceD4f@dNUPW0sQ8wO8g4~tFAqrK0FU_kK z(K>!2L{dOI=xWL_*Q$wlfFpgz!jyo^R}xFR?YDm#3Dvs*ZBR}E*3(U-$|i$*4#^0o zLq0l1{eY$V9UoQyvn1ti`(?WR?^S(t{S9CUcx_z_IFOP`VS=CN2e7m~VTgE;gc7MN z9mPnwu9}SXPy>_gL8z_U{=zlHl>8E{i1rlPQW$PvCjfp|9R-H*7QPxp9;xN1Gy~_A z27#X*#ZQmoC(ajE%638buEter^YFHAT4lB_B^Xkk~T2k~}UZ+0)te@fo zpCY%QH2UYon>%+HuBeTuNj(h^N4(%zPDQYD`yd$RkK2bo1qou5#>{Lpe1Yp`mXn9W zi|om;zLq~0IxQsguFn>W5VlCcU3y$%cp^4UI_FPF$z#3g9%Lsqh#U`?CrldEE?HRd z8j7LRG*I*sWS)kf=5oegl#x~ok)$->G*|Qm&Za}-$d=+aWmC9W%ifgzy2_SdSAx>AbVl>H3_E#+;>-m9{uuo1;n1ct+|XhO=#TrYC9Y?HY)Qc!X-?20Pc zU08NvajS<) z>VSjs#({-#c#dx)q6omVE;oxy?SD$n7kH%vt5!5eKx}8I3SmInn(6F%&F1WS1JR8K zz!h9&*>-# z!aq-$Z%O_|cah>i?Pp?Y@irEymt==;abxQuobyMZ+;HG;CK}XyxPt67oZkz%l~}q@ zJv4;YwJ!yDxBU#+-W5;-aQ1ef!2GWQaYwm>uAdgAX}r-B3y4EcEHJ%^Vv{^UJ{FrO z`|nAbXJl+vqC+R_!NWO{@Vmh!_+qd^J>fiU0=_`(!d7hXtI~h0vXk2AI@Yxl36(OB z5w6IWl;@JA^c44MKuq2rpd#_aeJX$T-X2$U{$0N#>Awf|d?iNg9>J2?tY6ZJqqp%M z6ym02ux)n~2&*Co_aZ@$ic}W6BcH_>buH{vWdoU0%>NN5p|$78XW>o3(~MNY^Ty7s zpaYjKe6iPQGaS8Y=x)^bzNi{TiiO>4? z%c#o7ado%6x)QtH<%1VMTS7PJ0#wr8VnhsfoF&)aa8zSeG`kNgXpkWs=$6`wk(!^b!EFDH^Z1%2L`Z6e?xgh4qUcjRvv&()zd_LZ1i8}<1 z4+D^VD*J!@oY3b7enaiPPPUs=GT4BT20R11pkCnFXB%kk0sDl(NvuD}u`ktGpuJ@U zqX#4v=1zlZ|kJ)A+$BG`@)T*!RV} z2mwY%!10`_Xpi&Vf#Gpg2x-8XfiAYuQIgQiVyT1GfN{bEUH%$GfIXuZWB)l_MxTm( z0P9*|JsWp7pXIvKHLj;>an++aVH>D@6sBqWO#hHS3!!anOsU0aUSEr>hFb8t#f1gd zh8n0ic0VDH{I|z zFg0!0ioQC0AsM(%Y7ead%b)5bFb>EiH+H=eMxg9tpHii547;C(Wuj=gZO>73s_tl{BEw$ineJwS)77UioR=RqA>^*3b!4PQnyT2SB zhh5X?eqS9#CjylpQm@B3waXqB*$Mv9Du(nRBh~=mj#-=W*8#|5)~j#@`bET#cxsXK zV50M@ky#aejCM#q6DxqaxSK{Q9=#c7A|HdO7l)4Jgt0j+55J;49Z|eFV9Do!f`ZOi z;2yp?YRv(HideX$yTt(%uBI1Uy{~1*?O(o_piYu7>m&1j{VEh>{!91^d-O6TO)u0` zytv~6SM<26_gC4janI=e61D>8h%0{F)m<}Un+&(D;>BCutQ~hE{%Bk-$AA_7*NV$+FdV~Ez8Lj1qnW*?yGD*? z*jAAo%`kFc8ml&-9LL@RxPRE2f>A60Ix&hJk?U4Gx;*)0b=h-nFbQ7qcB-nu72Tx< zPHd5NW6zH>iv1$5?3kwai_l?Mtef**k)Lk=BLHZ-NUz?nqQ=h}tT+}@=lY|&BL5_W z1u)wkhlj1wpF2cVV90ij>qW)6(Ze|JDXYa!n(%lL^mToZ*mYKRE;ViEcU zFWiG-BH-{5^Z7T~b|9kq(RO!*wUg>c?F8wR1kjZ-gmQ4LI3CWGwUUVj`x5(UY~9}l zrO7=tw%uRHJ%tylqVn)B44aM4TMN_Hq0g9j2vy*%Lpvbno}zuU?_imE-vQJM>#wq6 zG-aI68FiL!_`T1=FC0w~H2BVk};NdffC_QhW6 zS>2y5a>1rmVAszRxaS>I?uuiygX-c{s0M>kb@xh3LY`QbS(eye|!E z+iiZVj>+DLR#DT@!O+WSra@v;EE)b4-M|qm!|E{u%|G#KvaHT5(-yapPMW8ha} z^mxw=Udh4E;l`wwqfWA*LPv%kZT*)Lu$aQ;*4yYRG9FdZ z+~<0EgsQU?c~Pv-ziiv{6A}h00e7tpy42ZM;cECw%-XTybv%qo-n9-o@G(E3f!U!d zgcu4eSdoarAIG!FKyYpXft{`}TsTt0EHFUW4TCniLA?jtm%k}DaE4cm*+dCc1AArL zL!0_*uobrk0SyoB(2bm<8-%RbPvjo#(519zwVsa9Ib7Jq>WSOeEg(ANs|Q_}ZzE5;n*#&W>MGP61a$uht| zN^^p=@e&O4q%usAUQgT~gPoCcl5$P+r>Os_^HHwoWKy_oX#OAcEe2YJ z(SXiJQP08<^*8P1(hAQLYN}5i{f_S1NjepM8JZ2|E~I+uU^=qq!9QLJ$M+i2jcz;r zu7;ctFUA9+5TPw8(<9g*g1w`Xi-=FpXRzDnrh&;24aPkZDULD&=V}9fJZ*8N*7by7 zVLbRQFQOaF{ZJjQBg>HYd78}9^gBW))L(Q(z9?t6(Ptj}0?ofH@vAWqt}cg{Ro0`j z(2E%6>Qau!tth9qVY;G`UP4Qx7W)y4`BO9 z#o0&IGrTKd-yoHb4h+L|+Sfk|F{0C#5)q}be}6)rhQQl0UX-yF8H9T}cJ5&uPKOgl zw|h>6Cp-4uPb88r7y|2tF>6D-=;_$IM<@!z+eak*a{Gt|2Yay&bY%GE*lF_Y>IgX& zTjKUZXo+iaOFiwE&OZxkiY_M?GhFr9W6*#t%P=S&n2?qRe8)5+V{IK9%Z#{a-CTyV zWGo^f137;yT8Cqaa3l;Ex_e)Ns9vEhbJ4f3M-DrA!n4rDWA{qGVE~ld_Iw*W=&qES z1a(6+<9hG;Hb2w%;l{hw<(dhHiPTHzYlCT`k$3Cyr(#(paVq*wVYwnWpglfx+MEr|-*3KVF zG&JAJ|6n$%?zX?~U{dLK-=NcIKE_6LzS_sSSbbq8E3DVO4CR~<`wnz>cpC2CL^Hy< zWzWU!k3i7aXd%^6l_5uw7I{>NeQ26IByP{83U%HK?~{g^H@Y*~Lz5s3QxlT*A<;Eq zB(Cw$>T>?2stty2!@C#ge#zaOjAxA;Gkz+qWb7AGVOM)dR#<*_9b4f+eUO1#9=S4y zjvA%S4ECImJ%&1Oezoj=Fadc~6#}2n#B!-AFszHlII{G00`Io}>{HC-tI`RK+y6~s zBt;BuMg^}+E@6{E{>xH{CezMYx2xh+FtDzItg#toKh+Hni077?45+ zg?dNNL-O9X`&IPvxV=c$Vcj;1s3MarJ)|4xmYk!+T!h4cc$YroTgnosrE|X5cyKIH zZl`-ML@IwDmF~8GnZm1NBHM5;)k(f-#>;^*gms!{`st^dAs841`=2E#Pe~C?iN(=^ z#Ee#ku4D5^c_5Iee1Ahy=U02=2;q)wN*y8goan@PeEjaQdUwZDv6Zl8N>Gg_fl75! z7^_KOuX}NWGFI)7i`iJgP{CliBMl(90mceO3+j^QrC_dDkbYoLjn-)jB#o8aLW{;*9X+3#Bu&!w=^71rJt!YTP+yxVRpqp*z2Bn#jv zM7!EUcpAnQIPgm0Ntd7@b~jXrl)8bU6L1OIPSAa9Y`Nf_L(l{Z$|p3TSvGsDVT&|@ zG~$1!36BoF1rwAsaQyx(ay~rdQoM{a5C%HZQN%-WS>%*^vTE?g7&s%y7=W_i&cJ1V zb+_}cxTY6tA$)cNC`X^qSB^;o^vvVMMod~2pm#;eLu@o5fP-qpW=We&Y?5F}dgw9S z;^h8lEPtY(Be0>CKPO`OlU6^&*I`!VB3@u{`@H5)V1>&;QAlhe2Id{; z;Mc=C-zZlJid~U*WPm7lWQRPefTj|4AJb|hj0=@`g<^k*3Syv#HI}YQ>9rjDE7kkm zaJUKN!8f-qJ_nShY<@yFqWBf9SHlp(n>KBGQTyTQ)uNJAl+@uw%9?^*`A!3PF)yU; z@HCXpKs|ceY}$#W`s^v{Yf$w`^~+S>v*0o6yG+;jy|X{6KGS^K*$IUpv8}_j8vP}X z*-O-V9*QfEqKK|wi%UtZyhkuDKn)Sa-H)M4#*O;Obl6F63CkoCEEXd>C6YvGHc`?( zQU8Y?yocXGCK>QD>GM!4V83TNvbyb285@RO{5J04RP6nxdi>AN$j7_oV`x~EAAepx zK8BLJ^drA~)Y$=~A7VcS9{r1))S%Ql^{CDbEx{O#7Es*?o90u!kI?buxV->Cq{=0u zJVVm5X4W#P(iq)oA_Lz5^T<)|1D4X}5w2+dQ%Y99r3k8ukdlV{H*&G-410j-9h}Lt z++-i+{D^ks0yFDp*U}e`f?hT80m<|`8TdU!LJcv@r87i7K1)`2y{gUz08@1ySzYJ! z;RUqlbOX%DG3!oXM595Y?8v!Eg-z|e-T7Ivw&zK3;0@gPzSwNCM7TLa!s6|F`qV#n zin!f}=JO3J0w=IfyWTWVGc<4SHY8<7U6I{0>D?4@`z>dJZaILGj3$tbx~=VM8HWO6 z<<9Oav*PwX&;os=`Exm5edL~tUibvZTb;ItvU7I#gi6aTVLG3NNIQBrAi7RwZ+{IW zMQ@Xpxyqi5$sqr(qeKnnP)&zz59Jl@94g)U-o&jh(wm(gr@+SEs+lIGDZ7iJI2H0TVtz{*dFSE;uhoQvid0F6??*`at+K~s^h)>LSRx~C#llu0ZXE#s9gZJZx|S|@1evxy zkK*q!>kQlgn~3!Q2;yEHduAf;-p|IL8OS30NY<=7e=d?3{gei}%ADAG1#aMZu6q6f zSQ(397JJP438f&{M`qMB<-Z**7u^; zZ=(F3o?F;CWJ440i&$^NgV?obrsRy#we(CPI(%u2UdJBGrS@CEiLO~$$QNkFBverL zoa5GKVzY2{V&JS-x_)hmeFo5o2;HNISV2VWLyQQ0vEINL^`ZziVMSaycttD)W*pe; zLMQ#+!Y*FhVtWo~xP{(L@CQ`Uy)2GXRa>jkpGU|Dfz7$-y`{48g?P_DGNS|3lW3+$ zd%3_h^#bz!@T`-MzG8lq59L#jy5g4bB|y3m#poq$PsiQ@%PDC0<=)t1(j~HPRTYPD z4p_n9{g~(nnDAM<;^V@OM2#h;8Yxm}UCJa+#F{@evve455?0jVcfNr_(J(w7FZRGw z3>Xk4+{mL2gl^>7$fQ0?Cl}5)1(4rDCkb0)Ujq{`*_S~&lM>MAI`mH<9db|jht$)* zQb>x1;p+3azRt1x)n3bUQf4>{CbREZx)kMVNhB6 zg(5H}jI&bTLPg1S*C)Z&-#>@~@mZh81K5=A{9oXH=&!J<7;%1uYj`}I0$=QRAjQ>{ zGc)#Eb&-X-;IUF&vHMX7jGp0hMYCs>lEiVIXV~hZh2gTE5tr?I`3Hb7{D+0g<{z{S zze_x&vO!gLLhK>fqv2_>YjF>^;SQCZy|8C^LaZA%2Q9KfDg)!c6lweV}DsE-cCo`eyEWtrObfh9ay znhsYK(PNw%`pHykFV_3y%9b+UGJ1{RF3H0?bQoo2TfZQYAhOh*f8f6;598jCkrz9z zuv=r_m!PyTuG;w>z8|_57pni;9b` z6TvSZE{ET^6=-=9sBrCET7;qkum0SGovvGNi2VjafFz5tS~?R{W)WgL%A)B+buQgo z<$b6GTrS&a>#$Z61G@U+f3n?Tef9xdV_ygox}_Aizee(y^*i`$ksQZ7^kE>u7>qws z4=_CT9;*E`UJkz4`eoZ+5op;<7DV$kT@hmn^U6F^k6b5oJT^rZyuILHC7#=Pj zeidOu3{a#ggcuOqpb* z=HoNS5x2e+%HI84I4^br1u&le5s7Xv=~%bbas>UVYt~ByjYTEIW7fI4@0;nM#jag% zl7kX`i7oZhr%6#{N1u3Vj`VY5N73^@cX#cG^H4vH-d6)Z-D3R#z^>@O#(>t<{pA5X z#Ml697`Ifiw1nvF-7$JVwvcerg+T+&ITH1rK6(gi>2XE&P&Gt| z%yb^QlWLV?#h$&mjP=l<8&xGRm^WaE_t>GnNa@w>7=_LQPIv+|$^aj&L3dY=*zN#F zs&IG~l|G!WYIERxB`%?Ud0>4`w`*MNCvqIWduBhF<=SBCh`^N z*fE6H#@vJR{tr#FL1AntutNNutNVpvF+b_gN0T2?V$VNYUMolF|z#vA{&HMMahB5)@0Zo`SrwLZuO*Il)V5&j#+a+24Sy?#LK9+xN-8|04em%D)fD zzYog456QoW-MWWTX}tQ_l+^e#8(uzB<)AEr7AvR`&~ z{rV(!XE{#@yqNac(CJPD!fKm5+3yax$32TprS9{et!X-PMYNCtR|ObWDY9^)$}-Lt znq+$jY1iP0dt9Hp4Ane-?a(!E!$!>dQ!X{*7x)XSlm1E0=i-Cu&*Xw20v@;q(elujlk8PVeCK+nk=@^kq)-)~R}QQ%m@MBd2v&sprf2{tCX= z@L%NoyE*+Xr+u8h!RhBX9na;@NyAgPQq?n))5|&iG^aOkx`Wf(IlY(D2RQBHbdb|O zaQatHbKR<*^EkbP)8(AjbGnh!9h~0I={=l2#OZNPU+45~PP1xNJq4T=b9xD<%Q>y* zbR(xXa(Wx5cXRq}PJhDb^PK*cQ$a6a!KaYZ3pl-mQxB&bIQ<-_cXN6lr#+kwaQZr@ zZ*wYEt9qt#dI6{JU!n3>@%?q2wsE?X(=T%RZB7qydYsb%PT%14G>^i2A*T*b*Kpdx z>2^+U<@9b&ALO);(_eD>HmBpSRQS*1^b$_poLYL7KDW_GOHgnp^>1~|e%jqFbpXT&+PT%Kr3fqU7oG#+DiqkqyH*k6*r+0Ar zTbARCoc3_~T~6=dbT_B%oO(E2!s&UO=5hLdjcWHBoW98EBb@#Vr#m=p87v zoz7`Cr|-BF{?|A?%;~+H-p=VxPB(J8hSPFRi#aXi^u!9r%jwgc{)kft>*)c$*LJb+ zPnMnJzv;C9&+2|8E!FVf;e37nzfC>=nkDNW;Z);;>yq;EZ)pZ;L;)&G34g+8TqvZZ!GY$Ww0&YzlAjwTFzxjUivaxbQ+_OE?%ZHu#K2 zV@spokLJuX+B-tVs*ZMF-8R3E8{pj#Zf$G!-q_d{_63nQc6(CkN-H8U`2#+GW5DO# z*y?L*&WNY7qkUuRrjm5vzX`r%lds*^=?} ziRWXtkLent5E=y>RLhNxROLsOPX`9P{LSTXa5uTKSWAmfB{l<@OMuzr}RW3<(Ysj~Sbd)}`wI0tlIyT(k zYYG`HjX@~5(HIH^S~rA4K4bQ*lCsj^Y#|cLjdEIFBoh1q8ycIXd^fhXK}$Y%d(z4& zIkyJAO&weOZN5&8|KsAzRQ`X9$J|?V-z1#qL2Vt)3C-4Q{n+i#RQ_+JHyw|eUcv=a zv9Yx?(S65|dn<`OWI#CrjT_puUHiCv|9Jgit*o`BDRl+Whgy>3O)$Jc(T7$w2AWz>O;cm2wWFOaQLQ3=wz=K2rHyZFBdw<9 z_}Y!uE&h%G+FW9+@y#a>tF^JMH7F4oY#87ze1QO%(%KH#)pD%& zR-!mJl#`7CAF(jdN@D;RADj&=8+}l~CMf&{AJ__4I2df*)Gpm*V8f#}Pz@@ifl`QW z=xA*RcbNjHP^hB=-3CA;m;||s*(efdgpYX{wb>|3h@#O51sa=t8_*LBlpvs(a1a_G)vwtXfQXHafsQSy zRg2nI@EqI=VakyZGEh17d<9+_X|(Fwtr(pG0rKV~d~rf=70^7{W7M@$CxPM@Q|Zi3 zpz1m8J}_wuDM1LEQNvJ%w# zdFcMz&^2i)&`M?w?e|J&3G?-Yx%NTHF-|i)v5n+%YFLu_#&Ek-z}Z2= zq>9?4V90OwwZSh)j63W@7-N@{1QDwV7oi8;$w;c+s33nqVVcgOT4&A zd%mfyV?$$`)G4o*Zx}?Dr|~2lV84lPQl4YR#ROp`sGYw?I0P zxuYOCv9-qr3Z=b9C3Ro|1tEu7JW z<2GYVI@4Vl)z!o88#==6F!et84$bgSFu1Hm^T_@OX_VB|5>xSEv!Hq7?Fe{PQT15N zA~pmso24y2O+qj_lP|!2sISx46sB;Y!q?b78)nl75~v^1(65FP)!A==vj#iXNIt8P zz=e{DYXcq%hN)&_g|4Z(vo$0_ErE`$fYWvi<0M=oc$8i;Q_1`U9-Xh$La?DzcgDs> zIAP615@vl(Eqbaz4ws>VVAA?A4=8EfXy~d_tI+n6T6$Tofe(z|Wl8Fdr3R~JNuos( zOnDN9Q^#wn$;-P81OSjw#cr|GhI_5s$O7rv!NBpXgioj zMcxo!qIvrK=8h2Hb%&NS9`vW?c?OzgH27QnY8HfXN6*c#RYle}2yq_pXNt(_$l47- zL<1<$f#IYHL%lg(=Iew3LjEQn=EZ687`j)nN^hGF-oC0exvtU#KhTFYAa7!32%du; z8AZXol}0awsG3{BKhpJ&ir}wnR}%`gvH^bkwo%zcOP(`J9NMov`Z*gzno^#=iWpO(J562}Z@OtEA%AB^KV6hcR*YUELU9lO)@o9;B4?rTVRA z`IKZ{wnDp<9nh4k7z*`AGH{@p=9b2JWA}$*?scS&OKB`=BUP0j)uXA^YCWuqU1n1W zHBCrFUuag>N^|;-z%~_$XfzOKW_?6og3pzVAI>A%RBTaqJy4+ZiTVoZE`6?|1+Xe2)23-y(gb6s8-P^UZiHQv`j#qjN*6Zfa(~0m57KM6&Y7}$ABAaIdcp>O%Df` zERl2k;N^)W4_HhxpYkI^@)*P^s&*p`0`ZA;q5TPGr42Kh$gH=+rq%XA5<=v zP?Uv}wvI>>Ny#X{>h$pe*~wlb#8%Z~67*qtR9XnF=W;2p-3Ldp8Pln@)-5D(;Gp>y ztvzcvtz}G}vOT5+jZt*K&d_{Dm&d$V&O67{hqN_gs-qFZE39N-oAk@!t=D^+m*c7Q>zH$Tcud{zp!PL@Wr=lG*-tiu>l|55 zX>Z!*0h)=Bp)^gy$F?t~MeVg?t*imZX#S`7AL1(Hnzk7sG49F{b*yo;*wiEwpR~0B zP7Fs0{USY~_E3iQt*KtQvKE5ZOgH#|x2@zMkznZ_F)H??=nnS?e{F8_-KZTKIlmxg za;S@<%ewE)qYzfdRx;E|WYotI%ISck7iev6#<~X_Q&855kdusN>%e!gBv&G?qxB#B zhd;J4jA&Rpt?VEiAgBMTD%l&2Z5?5wxkI{#TU&!IR8f%P$|ynZ?K}k141ZhWHh7Q- zAz~3pP7$H{n=uiaPaX$c^EvZmr7mBfV{;gDY>Gy2GZrkwG?T2p0To9WibC%t5|H>o zqpIW!@6M2X9^GxhXYy{7@he2zz+&aYPM#`K3}Pgbtk=;t`U6WUnL z)s10K((UVLMu9N&L5x2Xa7ZXPK91Kf+0~M=XnN} zN)e2ehDSkReiRCLXd^({wxcolmkN=-Ltu=pRG6Fgxg;G%uCYDqTNI1$v43 zamN-OwaMPnLYEr<30B9`bvaUBa8j+_B2)W+numy$$-u3WmztMRS=~8P_Dvuk7EpF` z9YDb7uQuG_nHpoLbW;B0Q|cI<8*EiiNzd8!g-=GGO2TrL+)5_z72N?LnT{MdV=}Hl z_ioj7B%JJ;Jg|~3$V~h}c^U=Octpqu5cv+;bomKN3F5fQl05@c{oN=utI(s+QgVmWkQxdum8E1kF$IjMO#g$XiK@@gbpQEHxq zGg9(A60SHkPr{X^B1viMiQYc$Vr=q98nI)*Bm-y6u zC++^)6CKZxD*Y@yEB<5X`=j7eJr-|!qz-N*cKsO zILSZlobe*hVi#6_cEdPNR_Q$G;7%Z!u_Q+CHAVz3wzIeNn!czNTno>R@62l%4|rvARqj@5)IbY-eZ}y@>F@m>r>pQu^0QXmuv@cdXFyC9w7$?p+eEQ(z9<<^7JaPUz6U6lA zbA&xKQA}>mMH?oe4SB)=&Df0Z5{Uz}0wy&N<46h&j0kWMoB%EXTmra68m?*Q=7<9D zsNlK0k=#MWVd8HC$engR_=#tQ52Q+fp4a2K<;+}hX2>SaY(7n#S(h))1nx6$pE{`W zCn7%w`4f;oUYxmb>fp2sa>W^oio_XjkH!ZPifN^j#JP*A#JQFwW6FHMf;y*;6H{LU zk4wQXU!L&2Gf^}^@vntUXFs1S@e=HUpo3C40-wm9wf z+>xCA@%|apa>caQ$BV+F(0Q~Ww{D`aF0zT9uL$ubzDFfa@DnfsFaj_FFd_}ck~2=^ zY{>4(B3duX6BoUcEoQ%Ng^r>hfu7vvNuV`X41P_BllT^0s`SHrKkb|xVS8ZG$i%@3 zJ?8!<`Hxq%S2*3!yD1AtU zQT?tI{jPXS8PGdf()4|#U{LA1DtigamW)}p0cDj=O%sLBjn)CuIm^6UG0$?AFhB+;mIYF#^Jx44D4=;z_6+RCcg>uDy{A79$zRl%| zm#O#MCs0lRUI1R8JoO1PoCRae_=Q=e7UC~-H+SK9za`ruvX_Cr30Y!-<#ZusyDWPo zi|B!j&UrmsObbmypCw(%5hM6{_jde9{5z5k)Q9H+&jp@~wC9#@=8A9Dp$|SF`(Xe0 zo^1cP2GoBB`U`aV4A6JRn$t%n588V2{doZuohwA&Dg=Fn3t@w#ZG!Esn+)3o z8}$I&COd2i+GvNK*%wU|_BE3SrCkc;h@QL9&%bIBcQ01FGT&Ql*|7J}y@hPYLgPgb z-bHiM-4^k@gr`20nrA7`7Ujs3yt6?MKPUCpKfV+^TAL%*9-SPkgKT$bg1r9@@_HCAJvZN*%c$`T<5(TWwM7`e7AD6t z%ZxlR12$>~p3PX4D`qS_d*rOaY5iyP*!_|gjIX3;vR=?)e9Izg@O4xWZ$SU3JdpyU zbOQYV{k{sPA;pa{3zEpwt~XmP4-49U9AZef#dWh_4^Ci2G2VWx_Zy zVZ%6o7CNMQo+~`xvxuwl?I(Kd?(l18c zr<6gzH{(~bnW$tldAyj6{+bI}SiysR4_d?#d_7BuFR;IOCh&~-llly=qcXu-mW&rm z0F%pnmOc&SZ(C&ILo@Wb$0BAQh7L&l@Ec9{mV)u3pl%|@ON^Nd^9E;-eIUB19Ln?` zv51&1XS!Fq3%y0zB9zs-EBU;PJSgy4;)3mHhA#KvEe(%bMEO#*@r?1}42&D6y$*YR zG*{+N!m}!RM)nfd$$RRP6I04tNFIxTuP{p#-d@1+&KHg+ETRtIdkN3VJj_M1#d3^I z&ga1=(3y{Mjc6g5Yw^90>r1~+!82vNm=elH|5mbc^jk#1vlj8Xw1JQno(Vi7S*1RM z?_z?r}wutLPK?3o(lN z$9trXqHR0jQ2Y|#{fsB&p7@5kJTF_sUHIy{%=eZ&_`z#(M#c|N{|4MI@y$P>DtnO1;d=q! z$8nweM)En`Pr|)^KJiTWjPR$<3}8m!KfQtQ5+)~LW)EA$Wxzuz^UY(KXb}@PpiQJZ z0oI*-=;9*i^1|_+i8OwnhjD@Nct{FRw}KCk2)pHwpt**c`@mmY z1bIxEOKM{Stf~_zupohz&?pq*e!(OPc&;m(ItE zg12!?^CgQ)5cLwCZ4@(=aaj$9QUlAVtoq!yHcOm@)M!4bKZbmN0p@`wI6v}s0&brv zuNdz&I4C8qOQxp(c)x?<=|A4@p!o2Q_d6&){Nw!&iVy#Izk}k#|L^a2xW?kywmi^r zldl~sF5Wu1zv*a}XWLr6{wEhh3NhNyn(JzHd`p7u1Qg$+C~X54;{I`-ZP?w`L|fx) z=xky;aBsnylw61V6tGk#wvVg2DhbP4Z?N4Dn9xSVw>{gcd^oe>UFF*<7h7uOPH?=W z3XpXzw1&GjL<{vRuruykR%}Z5R<`(>Hm|`hZn=%pO?yVfv%rJ3BQHo(L?Swc+KDhA zuBMkTi2q`k6?D9E|&!1YjH%R4l7y7_Se#Sf0OtbsCN_(0BA)AA^pXu%Nhx5P0uhJT0D88$aTvwx46dc~DBcjf0iuRB zYf+1^n|F(MWqZfgc2{GtMV!v{tn^WnJ0OQIAV=-I^Qr{fdvKOiM8?i{)4m2~llTF* zVpT_A3s&K8N}fX#Vn?#gYq6;ebOgjV0WS$#r?!|L;_|DTAP{VXr`Mo!d!#bx7Hvr4 zl6!z#n;=oCMl+yAb#wr48TMRwu`K}$Vv9)9X7R6Uhm^35p_%mHeC7ainz`_M=sGN4&i@P-E&;%0c)mZISkhcSe>_6&+a6;j0st|2NouvF%sa?ZjQ<5glK=D1~ zffruYzU6d;Lp&|}3RR3;Y$Xw5F7cVx#wB|ml+UYiuG1fE4Qg$;N7Kk^r#bd-iF{~? zxEl1z9nfq+o}B`pV;mgUrMz}H0&wqdPF=9tYh8ts&u-Re!xaWpz`wXYF_ z#73-)bta#z>VTv+nzYUtTvxZeT!?#2d1SVarLv;VTi|jq@BFsGwgxtq`sicO8ujzW7em_0kYNEBu zM}w~rS4%xnqn!|!qeOzIG=fO;N@q_HVC5D`Wf1=d<)lt?e;4BGI)|Dpj+p9FB|OPC zNIA6P3^{BA}v?s%4=nrWANCF=M1lf>P9ko6jAO_d()GcCSG|z8HQo>KLPMOT3)^V2_K@F_! zzK!s7Xd6{S5)vA!#)~r4v}_x8e0h_8kh8s+JP7d_6DPGf2qtmJ-YEC1i22-dYL4oO zzoh!%13-{i;?YgmczQnb# zdxIE})FQMO0#Rs0zRol4^A8}8R9ET8OVWlBQQ)&2ck)3S`Y1+KIrwY)i!8Cq9>KbwXP|FnMhdgVfn23b#70PugEeN8g1wpLme) zGZeK$fK{rbyik=piK&y03Y{L5XZn7Fb|gj+IsB2=_broLlTsJrI%*A}^SV2*&k|9i zE))Hv5v!8-a)9}4@_r3o_9QMNdI^Cf>Tx_xcw?ZB9IYmLhy3X}$GqwFECU7gJ- zyR@X4Mzud@uL-qPHu~v&1AH2}NA^R?Q)Fw$wYnYW1ck`9;>lI5fewJMNuqq*+&JqX4 z)dcybBe2}pNVIxze1%?D;?KS^>hY=Osd(3PQuTh)a{#UZ41sz+T%H+G&P| zUJ`l{&ZWvtpx`66OJfqT)r;MTIM7w5N~$L5N4#l`wl2dnPl14YiF15je&4`(*f%PV z*ZRCE52m6%g2TRgf9w1$K?-foZwiFw;}{qniJRZHVE%&nsv#BB#-=UkFH7WA^4)!@ z5y^kt{r|*)r`8+KZG1i+*S~t9W8W0>R*?~`(W#HT)$wzkSvpPa|HI0T{1}{ObNaU? z8b8+HcP44Tevf(TJ{_Ou992J7Xyj)%ry396iUx+$bb8X@{QP`>8XVMFe$w%A_9>I{ zvlV>@UsUvKZaO%>;4JmL^i}m-*R!9W=P^Bwm(_F4*CNh86#=;hf0o1K8}ybR9N%u_ zZO}Nmz=s)e6atU&DA6{M~tv!UZC{z;_Nk2)2ec&KKY1pW)~& z=%r>Rs??`#aL%QTPJE+4BVGj4z6oj~_p{G4TIehU@dqO&Ri)1F5P>+ELvJ`tZ&?w` zx!{LN5B!{(c}myC9}}*W;SMsMkqr2>9-azL>!I#Xe%8ly`Wn*oHT}81_cNUMv1+e_ zQ~g}0J3l7eKHc67cr?EK9~15%!}Xj3U(d&c>u0#ZQ{Wr?m~bN+?k9?W4V>zBCQ`P8 zgQtKiV7P<-t?-p{n!v*s2E*;_QE)=1>3|>eUcZ!Ck2mSXTFz8<@?hG7ork&pwEXm2 z&(V(uckt1V2PYhQOhikS}m zT+@3n4S!3%g7;)8Icd7~u^iIN_oS6ie_qb*&f&E5fWm+1KUCVl^yzX%6IK4sM^pK- zuSw5_a}=Cs<=D>~CUL#@ramuiR{0uFrvBA%nu0SlAgBJxAG1HCmHS`c zruDCaDSszAxFI72pG^G+Cn&xbT$Cy|&A&|YGFVDQeZ{D+ah*SMW#pS1t5@AOYb&YHiOQvWB!hXK|r56d-Oo|)t|kU?HM3;#a+Nw)`D zUYYp$iRXVpe9-+<`w#ol?7#re9~?83eZVQR)Q?3;w1?sDV7S!TD2g!LUe=4w^AtXu z8cY2!+)37>lk8{UG+XM2;T&wgI=NmtBcJkNxEyX*COEYNALnX#p5&jY=qpS?h8xCL z%y32LE4T|X!1XiSfeRGec^Tk3nZDw=3QiuNHp6ngMa;iDnZ8W;cCtJgm@iY!xagYk zxp=;K=WJCke(yc?!*F+UI|hpt+=r=9>JR|(`nlfNECq)XfvF$HCm3#^(!z(IIS-&3@2C*&d&hnVZHLO z+%n3r7w>tp#AFuqK1hcsW<9%O=ZF+LZ|!$_k~%eRl)`y=jenfk|_+};?= zW7NEm+uP6e9%TK?WXDHXPkR_HlRenU{2Mt1eWlD7anVQHje4#(#&#`}{VQgD>0^1E zo5nvax1EfykMU)Ki!op74MkrjIKlW@&R1~hdavc?VR<;1FPZeYl>3{5`|lYU+OePY zpp)%TCi(7UxZ9X7nfluZ^DmF}C6ivAWPF0_%`~11ZpZXf^z%W+XUtUm%cOsO%)hN{ z|1@7Ud-VN&mdEo9r{l5da4yF8Bc@L-`fDJh8ec!_^O6j3TCWU-t7Co1gm0hLt5fjB z(E4(r;>&X;+UQc#SHN&R+}=!nj^KLxS-$D>b=?j>!!2U@X3~RlZm%&*(Pw0!Z-nJr z%yuo4-XGw4_p+VDk9VhhbbB2PcPHEXOm-+SUt#*v@#*#sGQNG>FEi=$0K@gOd^3$7 z^(>D&Sst1Co1VY#W_+3a>^qsyo(n#@e+)36?_>UD@~>JLUk}SSlRtDPxA*l^=zS-{ z6*Im}w~zUfBPBV0k)Hw z?EL`Kx0m^nsopyoUnV%smqS{gS-zS4wQ|HO3B+`{-W!RdPUF2~Ni?taFXDGoBo?cK|Ikjbt! za63v*;dlC34`K|L37?KD-O2qe6aRX+y~XU`XTs-TI1l%uOmgdCJ9G#0C6nE4VEGpjWi zR;KyFPTk+w9%O2-!T9{#e>2tF&wTDY1)oP)Pk+ws%_O&CZf^nWOC~!s!1We!KhFf` zVtsMV`e^%7#Pr2jZW-}0Uk);#GxhUBT(6(`lBvBO#&?M2o2h@CqIwAnQRUz1quiYhk!d@+e^XwzE7k&1YiF=X&OIrh1FH9i7~cOzkz;Uj2ys zQ6_uZ&+VO;K_1%fI=J5L#Yzt{&1(l4UySi(;>(?^FYj=BGx4RA+p+f)^VI{)zri^l zOHYihHRHK)t)Ttcr`OHvdu&MiK~l#dFFTL5pN94NdfCOV?Gn-U^ZH#Nt*^rf zIs47a4|=Yh*ID17Ublnm`2Ae_fnTqi*Zxp?em=b(Ui)pL?UK;rdD%Io=jYSw=4I!k zzTS~u53lj^dVMW@UN3((^!&W~x%W#$`$13p%LN{O71!5c>GPq%80hb7UjAq4^-XAh@w&hD^!zf~&R*+l=zeh>htBb^OVnLA?SEeWoY2>? zbsawq>+6`F=h(%|U#5DzvbKxYeQ>VVccks?WtX7#`>4KNuYMVAmm|8L*LnN;yn}Vl zJJi<^)$8FkUQdq~(AVp=Zc6*rLA^h`#!Kk*wCw=XbNmoWHMKubw`>clU|M zPj)-wrZzY{+H&IG*UrbiFRyK%ZgP%~tocLl^#6|MwbJj<^VVxF*YjiW9kPSF?$KRu zz3%S!G52@%u=Y#$_f_{k?M~di-?{e{x7}s;@9uruZFir`q~?MBT=JW~hr1pB*O@PZ zK7RC)niz}q9i;BV_RWrT9A4T_n)uSKH7y3 zgBDu&6|jmH-oTfcF`9QV)Ryf^P0@?>6{POMK@gyBg7765k^>jLSSvy5D*X5|rDC)T z9|CE#@KazPTDbNJrS_wF-dFKXk9r6#eD|lB1DfZ2$p`Grfp>z`j$P#Smp<^etEqiK z-2k4^RXmrjLTKSrzNq`dKe(Ma&`vy4^*fyQ9_-dJ5WebeavIS`crP%}!X`L~CYGrO zs8JwxSgcndbqj92muJuDBm68lhF+{SATge0z1)3ctee>Cg{a_0#aAt zo;voSUHA(Pat2F(_^d~mH#!WT@hEF7$HKQf=FE+Es?;4%I64o1?HGPSp6EQh@>j=J zyqBSdbJmOY5&S7~^zKCSKA1W{j(=%i%-cVp?R}?_)0cMPkAebPm}kY6g%&<<6S=z4 zJV&p73dU&Oc~M(VcXCw|msA5tA7Zt-?hL07@lw42#LszGMO{N8W$DBFJL*Lsz8|N;mSETH3l9AJ=%qj zfK~Jaevq01GR|Uc0jV)yf(d;AKpn#0LdpFhr7T>UjD^80a8!kGIIZKrCoRh zT#in|M}fW8aL{mS1qfdOZlRCxUXVu%UsYUE23q(gAnl9!{ugTjNKJs(!4dihpIjmr zJX-jJV2%#MTPw_&ocL+@O!E70MK9+1mz@7&u#arj{%*FJz>YCG#SgTL2hkI;WH|G(4$xRTuc57EAumwz#5zvTOO^ZN@w z15P9Nz3{6bh!);(AM-{Fp97-kFnj>Wd<^(I2emK3Zf<|!lMj)1o&Lfb?_W|Gv~U9K zM`z)W^qp&o!qo>H-Gfj4nKQm0-t-`O?&bM9>Ck5WR1~_^#K-Z z2S`nU`Y)H%fIh;Hf+RaO_btihUCVku{ z$EoelIyPLa4I0yUmfCe`V2=sk_6K4J?K$|gKXTuRo@Dcm zm#IC0j>6vn692RCK_J&6eA_F`lRi24@8C}KaoBp5c!d^z63Dsc@L8`pdNcef@M zt%dK=`T)GDweT}qAB8Xeld~^`Zv-;Fa8_&Kp97iaQ}E|zj!wWcP-bqzn_qX@g?DHj zhwuIKl6s0h2jH=QafCPj#nAzH^%#CbAF0)FC6GDnglph9?IZYUFq3n^QX_DV7M6Mo zb8IdwwG>1POT7fq!cz0#7Wxb4z$*IR_ixFramTX;*%QZfYD$m`;Z5zQyo>L>be8&b z-#_sn`_sjjW>#(tlAd%A30-z9Z$Cf0O#T;gUy_|=$1*uQw?&qzlS=ZK-8YhYY{&A~ zuiLYH=_Q*sUQAk=>sGEMmk$Hnv}eaMWl1mELoVT!-FvpJ-0-S1&D!z)p5~_qNkxIOhs3a?yO16@#7!|A1tH``& z%t=)P)nGMLjaFmTR5e}AR}0mCbx@sDr&V9gUkleFwP-C-OV(1gY%N#I*Q{Ev)~^Mu zu$8c~R^J*}Q)_0;Eq^^eB5<7{F zlBHBBUCNenrG9BtN|cl3aapVtt)#G&ubQ*1FsrJXuNJ}*aqN)63I;Y9)<(5iZH^s+ zR@91FDJyN|t%7Zj2^R6y{q=A?Qcu*A^=v(7TV+%q*XP(fp!oJ#oDQMx}9$q+Wq#R zJ!wzdzK*{W?nF9?PO_8jC`j@20z%ZlP;*2i>7`ojftU5A2tn}aqKEyC>}U8N9GJ02a3UBv=}RZw#zzZy=%6;KO=~{OkEcfP)g<1U zvn;D;jjS>Ls_Mads2;1w>*;#N_FVDWX?<4rHv)|aKAUW$@YcNTtKz4s>1&3XVLUW} zk7k=j(`pWzqvotR$6tf3Xe-uAwbHFTzT0mNT9eka zJ#VW{uoLRUI`K}rlj#)j??GqSnRaF!e>c#Lbfev5H`UE`^LCUNrD17Wnw9+JKsi#5vM*BQTsdFvmHX_FNm&tDLc|q`Dj9Z) zK}2!mNq}hbcCkbviNq0!BBR=v9i-SnA$Cxl9h6}Q8AOz!9aH@E06Qqk4ob0u^2C)s vJ7~fV^4U=(Lo|{7BavieN0I=m({D!X73kS(Ap1ntLA8Bt*(?94d(yuEs+s$L literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/env_settings.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/env_settings.py new file mode 100644 index 00000000..e9988c01 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/env_settings.py @@ -0,0 +1,346 @@ +import os +import warnings +from pathlib import Path +from typing import AbstractSet, Any, Callable, ClassVar, Dict, List, Mapping, Optional, Tuple, Type, Union + +from .config import BaseConfig, Extra +from .fields import ModelField +from .main import BaseModel +from .typing import StrPath, display_as_type, get_origin, is_union +from .utils import deep_update, 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 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 curently 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/error_wrappers.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/error_wrappers.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..1bcd4e87b81f371b922d1c5891e9839271b7a8c8 GIT binary patch literal 117248 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

~0W;tl%}x-%o|YU!E3mV;yDu7l;kfaZz; z{YB}SK6crcygr2iT|Jr&6nZsSj`9~Xi3z^89w8Zwg%Lx#TLranYQ(1Sw@71ZI`F!k zb0|AK!Nv;ih}zg6r`57C7lxEJ)+Z`}d$7tC=ol5iM|cqAH|yYQbxW`Cp*I<6HUy(4M?lq`jUlN)s6?#5P-XIlII; zs}mrHf;`JR);r4D-9TJBti4x3+D)edBVh*H5IrHp!GV704Z1^@uq)OlMF8|z zSK|tQ7a4saM^*;*!$bmw(p=5jT~&iA&lbY1{R%0w9_#_?yA-1X{|~|~ zd5#bB`V{hfdZZ#6NKIb@^~GX^$hC+ZMKt%+A>gSpsOJHr8Z31OHH-xa8jk>Mf_xtV zd6e&cie<*Wub%|VZm?{!diLo_6g64~VWR#U22(9v;B?tt&>l1G{|T~6qReH$fN?k{ zFbr5i+l4{x|6%XV1EZ|Y#s7C810fJ6AcJv1hYE@d7?J>q5t|_i%;*Foi{d&7$v~nZ ziOCF$MFaz_ag3L1t+l(~w%^v?+ts$#+E&6M;Evi_)Gn!ddnd*Ptwq$f^Zh)}dEZ%* zV78F5S5*jiuYCs!8q7S0Jp~pWjKh z+xCZ9gC~iq{n<1I8}mu1r}n3f820A}lDXGgPvOKjPM2;@t?0K>A%nT4JDa4!#ALz7 z{oAe5XEN9Hcef0KSPdAPc<~I=YbSxZz3MJL+c^%#s|A4Els%;BK)D$-n5q(s;*H;u zBJts`K;jl9G2TAguC;LXqBD|m7C0DJY`$`LFb(1R0^#~Jgqeze{!W#xsT;_S6a6O@ zjkzz6mDsEw6R98w4%)yZ#?s@3eAyIW9}ERDDE@OT)N$F)8-?QcQ3N6_ z&ry2-v7hCM^Yf+>nKbAj|ISTHBxWo?`ptpYXa$9y9_GHCFj&1BRUXw8wwnCzMUS1xbpy*^!8D=qkfkEMxH-{xTh}@lw=9Sv+eZ)d4{-8 zfk>$5`$nB}3usS`Ivp9CDQM`Uqf`N4(38p+a}4&PLGS(&*xv&7>4BXzeIQrboxKRc z_u(lwf+#Kp1`6ZKowo~_{f1(1P^aO=>$R!Bx>+eEb$&wXyd$el90R6ICn~KQQzdVJ zR-7MBmrQ(-lK(Qipg@1->#LGb%8 z6?}~ST<(z?Aow+4^KrQO4a?!?xY$y-`4^j0-0Y(raPyTr@1iYm**3a!I5*!(fedaQ zWVHw~H}3o@g$7~8#YnfsTHqla#&>NeS*M2rHK1`Qr=97JjA0SP%cQNRqokD6@iTiT;d53 zR|Kvn1_Bc#bFcR%3MYy{AY-ETeM}-MH(l|+NyV3I#UE>;w%;#Zylwiuuvf-h?f(KU zluX0@uE2fyI5K6kyw24+^VXSD_6XIlwS)I!v6J5ZO(}Iy1MHnY1fKulMrsuu@+|-l zGl&?EPE`fkcVBb*?y@Y>%~dNuJ7CD#Uc1<};=%OoQkMI#FG-4xk9ZcK*Z$ z@?8FiP4b=xEKEJuKG{@P^6a86^tfotGk~=7XFy4l=Q@QobY6Caimejoei%jh%Edzl zU%dkdD_>not%)e@QsPt*gE+tDEqoOdo;!51Hb*w+iKqF$?lye2^XDKUG|2%4Xfp0b z$C}^#521-#^9ke;A1p*8oL1SqB(PQhOG)z!8`hU52x*2i$J+){_)kiX`>Dnz#|f0) z`7kBZw-AFMqa|~%_jV!3 z{*#0t!?@+v&lzrs>^xw%=C$!c5}1RknTdQfiVtd*MUI1YiV#{e8|fkT2@^|PccD_- zVV)9zLZQgc$84B)19Jp<@ZN$%4QHNh8&lL8xC?4MnMJKx3Tp_p^Apndj9Zmt3-UBJ zcYIPhdDaBFHtAhNA2^oxqUYrKBMiZJE_NEk_cq1}6b!*~@PcP%VON4ZpV=X@p0sLv ze(=$z_zwEQELlY94%Ro4-fwKs1`0Ff(m-}-HSYYKG?E2?C3(Y`iE|Ycu!U3n%I7|- z^xd%Y&lDQiO$i(psmC~`zti?!XetpA{08}VCX|XKlIx9u|I|jg|3q7C7F!3gROWt@ z#bUGeIV?5Fi;1dEkZIMGxni0G#%Wl>=kwbHZ=DI+o<*tVI9cdQdU zWUTVl4|tN*gt3XwBD5lS&#jm48K%U4cc*D~3gDmsoC?69mK3m`2ds+U(@OFpKq7%c z^3MTA@Y?w%#f9WAHEoC#A-B zW7=97i^_W2&Lb(r2TH+u80pxbLJ3=AN~zPOl!c-3KiosT0|nYv@844OT&eZkp04L@ zq-*D>bcrX%j#$qsN(^BXsqe>9dV-c_Zq*vNm(mFCyRfXy>Wu;VkT)N7WO_e7~XT=MIyw0jATVu^eYQEnr zTawuU{dD52a)Bm}r+jB@>O21ev;v?xtnPnU8#0G(9Byg09g+TeMAWi35Y@io6U=7m zedqBCW$L{^#O~Q}#weWZu@oHp5`c_{FrcjVVOOf->jfikx_uSOQ293~NvC#du;8=s zIqZ5D{R+F*yeG`_Gzd9r_xLyEc^JE(G>wsEvTfn|RW7PbF${_3~jF2b6B zoa)<09JXMei)lrgBqte?^xh#AI3)Q?j*vE+B#eJ3Yxj%v@|6_XIbEr6w*_M@b_)pi zmsCF0b2&im%2;o~(iw)jpQsw@KOTj79-^Ew)-%LlERi#`Xq>`{Q;(M_vkY|_^)n3W z&-U7=D;8y-4i?`NN(-;4?KZR4nan0jh%nm|iC@l>8r0QGL!N0MZ^(lD2l`-`c%xh= zy*rZA_rwj#F2cZb0JHNP1?f!FDXJX`Fw1zuca4BE#^46%!T8SrN+UPRAomhNpgpFr z{K_EtZz7x2__PKK3N)BI5#ECZJO3)+LY+kHDb#xh{WI#tK{{RD%`>@IXm0RH5sWf@lo@_h_ZXi-GDIKw z3l*&V4*$@_F}{frH~Sc(`9p43maAVFIAkX~>s!b89wXO4aCDtt8dK(OLS^r9Vs_!w??Q;^>t4)S@L#aUkk zdA0-cIr15hFGbe{y7y7~NbG0OeI|4t0t#VMJ(6}z5WkJ5$W`BQ`&dcBuZHmlHO6w*qZ3&+xh zx?eAo{*imL0;cp0S~FE0YF4+XdvDpEP&~-za~|_-yGx1Kvr_aUU3YpY?k|9ww)btm zIMBVTa7UngVzeue>>~o*`Zm2aSQ3oy%Ix1Qj7zvDZ8u+gfvw*PRCt@|Sk7P%x*y~X zY!)kqSqgD&z9wA~&#y!Zrv(}p z^U&tL^GTANY9@iwu2 zmD4G;xI_t$eStE(s&e?>(u%``*lEu13CS-(mntP+Udw}mR@pv!phfddEb zAj!pQu9UWX zKwFlw-Xu^{ZJ9z$+rrf3C)nRX?T(#_)3XRjDYdDcI++SbU@rJ7>yuD+d(+?Fk?$LQ zaHO(;R(Iq^b4p$s%z?W&uq6BVQ|;SMg!Y|I`@YUFhkFB?w0)C|GJ~C+5A$G}ux^hh zX>a}|f^Ym#MpJLJn|c9FEtd*t>IUt$bBLLyz9db(U7BZ`n)dc8p^)}|Iwx2cfN zLaQ*PTWJjIquh*lClF$Juvp2n1K;`^Ulpiu|CS_FJo^q222n}Z1>(0ls;w-o+D;bL zX3IPJtvXY`QTo<5M0fPT%>%#U6UBk}a22f^Z+WZ05a!9AC_-sJvz{Z;Gnal zKhRQq)L502PM@NpD%{U0=f4m;*}e%IJ5rYT!-wYU2$iBQuH{lkcaF5OT|QM6zo_8I zu3Y(2qOe-xc;E|h?5y!!-Tl1_gp*@_*)4ixm(S_!s|t_o8YOlLee}4gEm|PAsUFNI zpB4GJ=xrStv9D~EbcPNP8CNh^V(WtTii2Zv473ua&|}z-CvKCz;Pwv~BlB`XEi0e6 zO5-dlUHR4iRMb{+m*no&)aQTsP}Z?N_c`LHHb=btFpGtT=z|RV5sG)B$vO+QH81cr zQO_Muie=*%cSRxJaNs#8cCatEwqoBVc5f`$f=F`QEIuVr@uFwjuQYR2Zuf)t(G1Je zdp!y7b!)`3Dm~k-(hLi8+Ekeb5iW2t%`-}DxYA`W8OKSbsGokrfY?!B$4CR`V& zcp-X6Mmx^dc04Q2#1d(PzzLM+dbX{WkANh1o3G&p!3&2a3m-I!er8H_*ibf%zr zwx31eU~*Tmdp8~Nxaaokh@*v3b6DrEFtns+{!BpOS%D-UX%~m@P0#Ji5tx)V8_75; ztp@*KI~sOi{B3;c>kGx*#(ba){VPk}z`O3pU=yjw_s%8CxB-LWZ^pwu6zFNeMSOu^ zC4LD(eX#f9elq29-c2N`{Q8xi?T3WmIGc5}G&)lpQD1=1qj^75FX(%2eK7MqK8c-~ zd>CIDQ;C-%5rq-Q6P4ZKlLE<6cCw`CJEnGf&>Wu?2@Ccd7mAbPMg;9j+$cJTAlN;V>qUdiPzIUzs4M#T5=VC|Qw)MVvjg(~c?R9=@9s!zwG~5?A;-`G zW6DEbX+Dc6ZZe+r9>EdVKV4j8xu$*t4s{!ua`rPsohPrF?wv_<&A# zv$tNzsvcX)#PNN5dO$j5MEi$hl$C$ry|-1@JNgWowu;in!%1;WZpjg}`5yp_ld6pJ z0!JON3qBn|h`Thix_8m2#7lq0H~Wcne1&^#1L{0rEB_1)KUc5om0IX})%7uqdRL+O zrmX_>Z#%&Li|AO@^Mh*`em3gq6H$1TNpJ7f!g-?Aqg8wZ7o8VU_00zpYk0xspv^w6 z2~GU!h@;F8i!zs)>!*bkhJGg#!%!)j62gFQD;$l(uu?}e;`OHg)D$jr+};3`2*uy$ z8&@y&$2o`FnF5(S2-l} zlDGc&Bid%qqFvRVMFWtyD8ASylRdYR=RRL_%6*moUl#HFV1R$BJ=Oi8(f>J^6N;}1 z$QMl22K$d#4?#@@?0Rif_se6&E>AqNt1>z!)O&H!U>^Slq{fQ_72LiaJDI6Z*#+hK!BZj6 z5Bh?mpJ1q*IF3oG!4v389V&%H<>Lczw^bWe2jfR%;$j234m^#nyG#@;{xRE#rKz$2 zuth_t7@~W`cBe=i&tG#Dd3wD^)pKPW_5)_%oXdrsE=Q(+NH?1Aj|Ji{a(-D#p=G1& zzXlI^Y%qJ>pG(aO%!@W>Vto73$&M07QH= zwE8v8A{;nLH`NDvYUH<)U-Qrpy^gE~5rDE|dmmzV4AsS}lSgOZPCTmxf=h<}$okZF zDBhA=Q}SwU{Ae{3iFK+)27>YJ>NZul&w|3ysY2j9@#c;WaOxAycgsp?^3efy7hARE z|C>!CR&1i~L`Ym=%*-_;F=W%UtCc|7O(8U6C|<`rf%gmnUCP5$Uh`G@xOdyDQs%M5 z-^$d|GF<#R8sb1JTl zFG5|j=kaGCWNW3fMJ*5c#IDeHnKDXk`b@>3-^q3v%IT@((xPs@K5oU93o6%!K^)8ZMu;U z4V&xG9gQ`jIHnwlI^#&7Ig#+p?<)_h5vOQnu;(T#&@&Sym@Tf3|KZF>$w;QM`G@D^ zHOgHK%}U;5Wwt#4B%_5u4ZRPYCB&b>8SKD$@@(5Aj6iCU{kAC3;~H3_iR|C0aL)o% zEF5I4RdI2_P0fK`Kc_4x5qi8(oJyEr+Z@e(wE*NgL{1p<+Mk=&?6FlCB(+7qO)O%V zESRxt%Wi?06m+}k&Db=%o=q}M^`C;gQ=NSHW5R*K+mqhv)_M# zQ2(i(?t5vsNc{POs03Lt!u91ThLAX#CUd zwd(3sWe8@}jpZ8j(GJ`7vM4*4D<3_$yH0RYeu?QkhiU41p-9>|IzE`_m?fe3C2;j0 z{po?eXZs5}_msauy1&;u4nl_H)B?2p6%`EpO@HZBmqs#0h_D@CjvS;G8OfeVR@Uxf-8EfVP-n*#86 zJbTgFmDwrwRprPYNjClXP7RC=?`Kr>R1*G^qlH6h@`~# zi&ReMi%nT6W z5uS>_2xmjwVyS02t7or;@SHD3Pn{@S((7Hy%!SIW8_KC_JnSMqY|zN8GDQqpIVkRm(J<;b2$d(YxBX&Wn&OM%F;A05iK zn*pC?M$Oc)jdQA(bUdW=k~Xoz9z+9(Ut@qQ&gKKYyCJQ_kASy}5)Bs<<=yp*zw>%!eg^+OA$aukUzKbK}x1HE=b9SB9aoGJeY7n9WMz1110wi7p9 zP$?v^HJl7h%a|`_N?_Z|0NJ-yNvH>lSr2#t?*?LWzl>`1Lj&KFiYnaK(e2T3JoErH zc1oaP>Vb;{gQu{7*sJIG9u^!!4-DSSyYHHJtYz)!S40mDqB_0TJWDqs^z=q6gt?mu zEBc!K!(0u5s#B%>RN|9wu-JEoiLx>{vGUd*2#QcI5ruSvjFd1KPbJR$Pni{(?Xsu% z9pBu^4tY6QuxIe5#BsWOqJGTUq;~@?36wXllxc$eSA=Hqi8@yqSjm)seIULPg;IwK zX|Crtq8jHln=It=!L3y9v2R&sPQB+pLxW(H$`ST`{39TZRXPAYe|}J+ z$m*%|7P60VV00WLmG2)xq`|Xfu^FqsPkMGZp_npO3lb!Y( zMgXR+Y;>O(7*A(pq^0#kN;FXtSJWYO@%$4^8xHHV0&Vy$Rb;D12o_YE@tkVO#P5}1 zFR7EhdKCHCzZgR(ePF&Ae`&4^U5A*g?MGB%M0oSvDt=TI;z2s`=|rA11z{^4VF-M! zWbgHU+d**NPy|_jQ;5Qd(d((;yUI!BJbh7_Xre50h5{A)ql+^J05_eO8mCo8^UWrR z#E;ITBTm$ja)d$#=%Dd&Dxt6_&qUN^?(=40(l}Ld2Dw%+8f-WQv!exa^SYV2(>vG)lqy zQ*G{(+C`HRZ_xr7X8uXKL{!n!iF0+e@f?@=eq5U8FR4=t5$ai!Z6UTF*>D^a7ka7J zlZnlLVNFPTsp+UNp`)puqS{b-z0p+VbV{bCLQA2oxC;wx>(NwbEO;e*gPR$if1C*k z)l|}QHl1}q-xNJ;3o9Zab2%06A2C#rZEf48Z=wC{&yb6aQByo(y10wEn#-J8)x??o zinbzxjQbupVPPNv#!cFJ>JQW>zD9QoN7vi_K)bAN$W+(}j;L%1!Dj6R+Y~39CrFNHvxF0b zBmR4w@W{a1=$}mSa`yX)^HC?N>qXWOeF)NBj81th^y>{ML3ZHajL0G+{6fsf<3T># z`VXEHJhSDm*z{$-QGoTZT3wiZU@~JAe>#K%y&=Geqf!*AFEK-Pvf0H(wlqre8n-w- zY4L(Cxdo~I9clcyAPbn!qg$?KR20w@l#HfaM2bo!=FX&)k>bnBgY$9m%&Zi2)WtSu%4FGLuvO{Zzfzbq7f=G8nN=rf;2z9Z!rEdEHv*BE5JUwR|O zhnr-ruc-Uy3RdPhZ+{E;;$^}~;`*|rf`rPAwz5@^`#Tgm8{Jrxi8t4W;v1T2M$aPL zzD4!?n#;QdR?IE?j7tQM6IC@I5T{{E(z{H`V+>(95cgK1Oi;b7R5PViX}WI-kT=%{ z;@6^}*D-{q@<2};2_O~f*^H_M6XO(qOvOzBIQJzs--zwU(Cg&7XzQy2$@(IFFhatZ zieB!+H+N6_B$y_x4B4X-u>@D*4+lrIDB9OEW!B9l9ntIk zqRvjBq+QhG44Y?W*G7HpPq6X%*9-sa_|zMGls&U8TpFJn=mYR6cJR4@dX9~c=nq>y z{TpBy>DCntyOF0Pqno(I?{avy(VZ$F2VxuH^MOm>pi< zuCL+1W%lb&>+Aiz>TzC`>8lOxl-iB~=GCXwv!c{g^J=;5YR8QGC=77+3FpTt{SYVq z7z!M^fI_hP>|vgxaA8yC5|55uD}@ikdxjZHnT~y3V8!zzm5RrkjFRnrXX1=qPAZ$G zCki)ok21{1L5YHxu(}Tlxh{Dw84kr|HJn zBIvr72O7GLX|&pSCAtZ!{)h$Up?v`knGAicWHIxx|KW6}8Mjjb9&xxXBfBDAxx&nl z%k*X<<>VL0P=3S{2iwk9Y(3i_6SUF8d=&k#AREvBk-WkQ#G#2Z0%xkPL@d{|5NgSv z0-X~bo7jJdQJp){af(`rd^NmEO&?p^<4a_s7O_I2u4MqfNe0}gU!%@Nt*Z&k)*d7K z$GVGTL}yGEU1W+`Yq8D#HOh}z8lSHBvsT0~{Ix**ZMG~?CF6uEM$y9V4TY9x+Y))? zyAaZ5#Z{L2OOj%lDrMB~*?zkah)tFOwDT7NCA$OXutDvp>*jNWC|*`{>8JNt7B&T5`~qs<&zjHR z_bKyZK*zYDUd!x}GK(m~R@X%ZT~RiP?xTQa-dY=9$GrZL=(WM}&4sjuPq_Jm9RHvN zjDNY2nWqij!01CVwunFHPhLjRqXUZ=pupXqr5+W-hj^e!0DY>`CNo%0-jg&h`uMNH z7e)|qjSdQU?-fEhH0{tW1M&R>FRN>mzg}|mdVk2&Yl?Kgm@kl^lo60?_pIJ=3cDfX zmuH7g{6j9>beq&fJpjuoqzAdhsKR7V#Q7Yh@>3Ec? zWKdc!tr6;{C+pM0Y_L3rDDT5$l*tag?7vKXEAslm2(x7e=Q^Dcn@wxR&66k!^)L^D zIcc@h5WXYNWSP!x@OGhQLm!EbNX=7deL_a2^s~>41mf2fuqjVGkT*70h1mHk`%{I% zWcxAA^*OU6Wm>N+{lGie(wPPiwlV!NklYt!gK41RubUpB3~t}lVx{pOow5*ApkA41 z%*xDzAT;58VU%9)piJ>e>&~au>@Rq11bU5#e<(h8{x4Ajakc;<0y6sILOK;XA*}a{ zybQ&6h@O&FBZmIZ$`Q1#QmIc_Ai{|d+GO8K{i4!ORSj;gtYCgmf$4UNfv@r`gTy*# z>sghcPd21R2JFr^=ylSC>vHqNGv^dO(T4?(4*_xnyyzZ9(k<+mOZ zK>{Zv@=HqO4S0m!LqC(c(f%ZFGs)jH8mz5n1fj@jwM9J4-YXuYs`>WCSeGi77s%202+vpw6>d$aU@d~*S; zDmtVt6#vhXWc)48f^NPT#x2~T{NCa4JG%;@aiBzMwfP-ISf=r4Wgz|s-DD^ms^3cS z`$D0fEW3SZ&YZGin48GBf1pm)2UUX9!2QZg`8CqsUhff|yM!TXiW$G{7Yml*aNH~y z3ySM_Q7C8%&MXh)t{xHJdjOJ&uYAf3E<=$I!xy#bsb26eU?B_S`47-C&{^Z4^S~Tl zz|9NR3ZAk{K_`pM21eYYtwtwv5SYRb9i(F|1S$xA z(EdjTvogVKOeP9CsdAOk-2Y^}%G|JwSAj8f2Gqs`B40{(K;+kSvVnRpr44EK-f5^E zLcK~QjK5M5_$T#~SL(0)sQRA~TC*RqSuTDSaFA)er^A%ZjXH5Y3SO#KTNr6F@l!ENsl9o~FF(_*)gkE)qUUi0E zarbv-Q<+ZLe~qUh2AIv{I27*fl1EsohVzY?d7SpYko?zsRb&rHtH(S2rQFN-rl(u% zimBK~>>fLoIYp%$K!L0tPWNYw(VzG4vjhr<5qbn(ut&|+F`LZl_!AU}>XKVpVZ>xt z&mfeAew&!DRZ0(%(ZM=HAe{EuXN|Or=LE{P-b?k-X^Fq%*r9N99o#w1;xyC|-HQ}u zTV^xnbF@9PQtc6n&>khsvAU4<{O#Of?eS@QPB!iNolZH!IVb;<_Gm?hWi#3{Yj}H7 zU1h7H8^J(2(x{zu|3p6tde;bgY=6s`sPgF^JpIgFuXnA3-X=1p$xW9Ij*^9yp8E_L zBsgZbW->^sf3$>Y4|a09&^1F(_2{{(G}Nk+~dLa(8yw_vXvu1hC{J6aF z4Sl1kLEfN-vdgGCmN#hf>^C&R)KfY14Hm|{Ip$>e^>stbtaQo@o6l}`-VB|!j;lCP z)#O0Wzw2{0hH*z=pR5mm!Si2T_9BE5nG2p*?7HG1gHB`GoAVM7KOlk zwGIwb^X3alPO+!ie<1yDpIXPtFp(o1Alvyt^Eehz{IXucNjG&E4F?<-i2ue;=2mtv zHH#t{$sfXKBx~PiB)@8swc|6ApESwZ>lw)pnB+ReBwgj#OtSWOMsATTs?^TLYcdGN zVu5(7m(!_XQk}j{rv|m7>~j~U@6IkcQr@*;^XblcK<&JAiTrfWy&^rNTUVINkuIy0 z4pRq8&)N&sF>=wdtX{k>og>HPc4Y{oypLa68Dhq#H~%%iX<_FW`FK6bu zK*wAkuwAq|UWYr?k?Ze%+2iki&Bd4Fp$boA+Uxy- z;+lV3288Fy!dR7IrjCvnHe`=<(;_ou{H^qht4fCLr!$Ouhk5u5a$+|#9sgTZAj^uvtRx+mn{*1fWdr@R+|_swfW>#wN%( z1!f!Qk&|!Re<@@54F%%jm^irv06;sl zg3#C@B9li6j{VX3aw2j$NuAG zZ7!_tUFoW+cyZHjGG1;T#nEyFl3o21a$Sb6nynplUdXJR)d^0`tj)kimHzl4;j6Ov zJ4tULl;*ZL8eb^q0}mv^>?VjGhT^%^@jm~1hXzMiv&Mw+ffv~Zm|m8xA&;Ls(*FEi zsLs0U+_?8Sd5k}q_z-ERa6dxqrjrBr1V;B&msdZM8}oqeBUUw(>lo-@ZXMh^YSF$c zYe}lFh1SioouEDl=W}|7H2J4l_C7MnL&2v)y>5?+ZT=5gk6`}pbg3{Q?8e9)b~{TF z(1OfH4L$C|;eoSdpYH}~kDQqPp0K85v!|ov)R%lqo;kT#{m7SFjd&lHoY&m;6go&| z*FD?!%2R53ec-1=oocz?LdD_G;Fp46!ZGhwxr>B0)h`{piBK549p8s?g{)`Ny2{j zKM*hQw|bcE=_yo;!*`HKtmZzg--vQ7fL%h3hbtbri3^(c(beVA{kgG|Iikab&ZjU5 zauy`{v_NO61>z3g6nFm+02PVY?B3=|Km;0p6WH}~PSP9sgycFZow>4SR-8=nSzGxR zyl#=8@i)PW=Qp3hVq0L>pK=1DpLXsS@D%tD2a=BkdV_~O6FK}-@%+uN*N#4te57ZV zpMnc}qVMHi)N{&v%s8PtX45)378`#~CY-$Mm4&p{d|0TuXG1IdjYu>K1Eyr{T^Jv= zfy0nm)5x6L)|GwX95|Z3OUjx*=gP26IuVMJs0-U`{<1Mfmd$EIalJrEOz7#gO#he* zl)S-SHlJ|62-gtwrS4DCu}P0P9`zU}@GutK<-ky@7(BV@V9$fnNhv3#rsUZWM8b>N zBvsW1;#*e=7eZLBS6Er#k8{7mOPf!0?pFwv=SC}1cPl)%=`AwI^$NS3`yJwXze2EL z7almm^;W1N|3Ny7Y@WMz54zRQCun%;|Dss3bH zVxcqPds9b7JDY@IIx`x32B&$s_@$5KfX#~y!{A92M3Gh-kzJ0)~{C<(Qd!3`qw6B&5X8{>y3V zXEUDK`npdD6L%-BBPii(INPSnSz^vzoeWiVl3w;mjD;Q;jXPxF0oRa&D`o!POGmM; z2Po>5{q1F3B@j9X7J1yJkKgk^PVTn8Xi=FfhFt98))6oxNB7a3O)tv;;&!bpQ1V1V zg>vg&!G=lN#@(I=CKPTNDBAM=xb@HLbwG0P;MVHtEbj6UIOmY(G_$EbGKG|;U*xrQ)FBrFe0u}pj#Upt?XVX(!_@M*R*}$7A$2`k8pU5~;S||6h z>P}8+UuDw!w^Jd3;e9!-BkO(NA!(o*T8o4TD^=t#nMy89eEcANL;PDOi7wgAQ%Fci zqJR9s@dw!>m7MY7DH-a;_BJy5yCT1#g%#R@z^+{dtKZv|OvYS$0=ph97`S`1bePB^ zI-#7APIRXHGo||jS2RO96Pw52VY(BS5O^Ly?;$u0X(b%+&}gQuJ)cu~8Yq-*M;@?8 z>?c%VFju+hk*~K)9!9fJOql|OTJFPQcf5A zCHlxjcVCitdK|G2u#AamBr!Nx2-z6sl@KJ3n;?#8?5xB!CcBUKlg#_k@;)(Mfd2B! zmNg2XmBq>19#1?A|5a{F#y*)S%mor0*j;9s{U@jKib@$k?0ZNGuo@qTW1sTxkbX%% zlXU;)Zl=csL8isvIUOyjbfoWw`?>IULN2%7L9ZxXWVBRNdE5JO_va|Tz3*mw^JXQ~ zWIImsK#zM9FA`VLOr?ykdqJKc9h;wMr)7yeX}=3fbkBH42BS1%JQb8YTY1~li5WZ{ zIdt+%-LJS3H;|hZwXYi_77G$P7#kytD{-_d3ws#k_5^b6D{v|~l_@K?Z?gpLDfb@z zoMqiCXM5kIir$4uc1^6WL7pvIFE%C*=`GU6Pv(3#>=!>Ik|aAcWULI;;=hGtiF?Ie zO}+Yj=Bs>|&%EkRx?=MHT1+vyY3r%P+mKui)qHMOVxJD(+@GNiF;3ibWAd;Mm?Vt3 zyE{2LR+*}Cc1DeiTH@|nQ!+LVA6+!{Aoq?M>^LWiC>b0E$CSJzZ^ik%ntij~dn?Ut zGBoEyKKKqVb*>X9 z>z$AGInYYRTzofm zG8yAPJ_^thEKHxA?yA>48b6gcw6#3Y-88)n3_|v}BgB>$$bx<6k^bnHmRhEy zZ&Rdd7?;%)aPFB{ye}|Ep6ktXZ>`V70}`+CQ4Fox?+cXhT*9nO$*#c9QRDmp{d6KF z>8b*r>RnL(H;uf4Qv!ka4ic4*%1F<%?Fv0COodTd@c9!VOpLYtFTt@c=$|`1@n`ce%7!EFen24zJuMQ5=gcUQ z9_PIIpgSOrTuI;Ifagc~_W&^VX0g%vKXeVgCp49^U8d~V!~^J~!4nf#5odUMmr2ek z?i(DN=q2()msTicQ2q;GGnD`53_J(c&E(tG7n4Gh5}hV8HqpYv;OiOX6PJ^cSjs7ErmPL1c6w@dQc`%`&C?Lsx8~s*XVXNv44~hjoIqm-D!K^3+IfYL9`6 z?{3O!TR)>fn11NZzX#nc4I20rX^F=Sba&#XnpGTG)6VbN@qushVC3KPfP0x}{6~Kw zqUNdIbE~^b6#Y8XVB#jS*%X+Z=rECS&?~~@;A^)5R#tXsuYt8?K`uqD_zST$%p|VA zF7Y390zEmCq49LEd??6_zG7X)ca$Irv8=4lz)|DU-WzoNnDDPkHd=7{XD?riFV9 zjc$7(@ie3@c^0~i-}VxI(r3Jn-KD)pI~+RhB*nVzg=o&UXJZo*M<{?jeT%?pu<#h) zWx5x+>Ynkac3c=y&G z_CI)#j!Ik(e2HRzaGwJ4uOt8)=>6OwUSb>2hTPXAZ$O<(u#Fb%?bo-ODXj?+_TGfN z5M3xR<-sS0W}SlGen4KLE$ae3+oc*oL=*iFnxz=A729v+O`=bXZrqf>nAc%6cp z;d0?w?oS0Ko`6^x;K}+~Z_Q!PT~MT&&2dyZQ7ScF?mv!G_L~6db9)1$6A!B$|MK*M z5G$~Cuh5L$o++Qm7wDb(VVRU(@GgPO-pZ$zqo}}B(6xGHbj2S#2aJss`855Y5>MHu zP1yrO%J!orM=HA;29~-D#IEbQ9V2|MMf`eoe3wiO#-H_XJ=_+JwEDNc)6y0RR>vQY zA7s3_%-2s^j9opHxx+g!vqvxUjob2iTSCddj!Y|OQR?pO+d3SQxMsl3e)dhIhL8gFwf$;~; z?RG4#`aZGe{5`SDptMy?|%Dg%c8S+@fJ@H zlIvjg>4&N-4#}6hfHb}Tg8o>3cm6@%R`yKYM-LQ9l9y0wgs?(^KWE53_# zX!rk%zjy8tsj{pwUofH14omH@&JNq`@D@9~+Yaxy!zb+UWjj1-hm*c&;8xq=Y&&#_ z`&B!>+736{;Vm*Y$@tr6r~ldx|7?ero$nz#exV(|%nm;>1kQ^)4BXf3@E>+K-q=9bROI^>(u*1!E zc!wQ+*$#hVhkNbtc{_a74&SxIJo)eme<#`DOgp^54wu+rlO3+J!yR_`O*?$R4)@t% zza73~hm-Cy^_**m7uaE)9X8wHIy=1G4!>-N57^;1?f!Vyj=yY&N9-`?bEY1j9TwYR zr5!G{!*zCerybsBhY#7|K|B0|9Uig6yt{4qc35hM0XuB6!*zCen;qV3hxgmzZaaM0 z4&SxIQJ**PC)?q4J1n!qfE`|KhaGmf*$#Ku;WzE@K|4HThp*eAWy|$sJ3QMCEA8+y zJ8ZMVEq1uW4)3+Y@7v)McKEQ}KX=*T7CY>)!z=ADV288q@Kig@wZqr`#n9n-JN%^` ze#;K;vcoNQ*kp&5b~w`xr`X{K^7$VA{%nVb>~NnQe%}tiYKNQcu-*=r*x?0sc(xrD z*x}!L4gA;b@Q@uoWQX6f!#nM8ug$Mp?6@MwKR@xiwg@CAtgkllEki;l|6)7ciT~dU z`=7GwecFT$Tugb^U&qF#hPG%+_)r5vEFxVG#SF-mbR8? zIPAc8^3NUuuSURMZlKT3C=}UXYHDq73`b)ft&t)1ek7cXLg8>{q@y$3(7C2dk@=W- zWEZ0DW0kwCp|z!{A==X3rY*^Af~8IEGKhcN@=lrSy4u^Mz}v;rY{bE6%3)G3hnDyeTjwJ-V?Y5^iW~3O7bK zXoh38=OfCc5EB?J(a2iq(leK|w?&o%{Y+o`s_W=_Uvop3udUtJ5RG=Wtcpb=zB6ac zE-C6d)8O_0pk6Jwx)p$twtw1>L-Q#OX;fqMqw61<55bMCjkHC54XdM(PT$#Q`_{&~ zqP|rTUxRNgI;o{?&ABu)>T}v}z{4-mFgheG1ec^^wRdQ~@Q{RKmHXKF!W|nogu5Es z>31Y9)`(8bV$FY|AHu`S&!KKxD(uF7MEgc4Upxc@6^>)Jb9ntF|IPYKht@w#DE@2h znVX5vf1w@o!b6#qdJX?M<}OX&AoD7n9i0(j!p7!?wlxu76A@LhvwYF!mM-7g_NG{C z#Mju+=4)?j-6%ZT+TPHF4sL0Swv!f-hZGddsjs86y)n|&#UY5chPBG4VS0lyqM9x9 zWN-+FSGTlAj6H4dY+2Ky)&V^i?r3PdzG02L>S*XhQk?u94bf(kUsAeas|B3}|@z0G- zzK-@Tn%dsh(CTwk5|*{gH&b4&X;~L(J4>sY(M4G?wrgXw8^6W3uAwysq}A=6zUw0! z*SB{zr64H62E$anb{^Qt)^lhLlw1lw2R>XD6D?p^@R*QmTe`X^?h_faErV9*cl0V& zLA(Of(=Ba{?VX)sJv9H!6nv8@(~U6AwS4QF;Y*mlwNa`AA{6p*Io zrC}B5oH>IAbw*Z45Qs(ua8-oTm<(vKrcKQWwezZ#UInzOX9Em!%oS=J+la1E3)&U| z>{kxO=*g8tfuwv7%Oq+auR|Xr4$ox@o8?!;E*V63tmyUxIA1^Y%Oa>Sv2{oOmAs#n?82rry-kV zj-6lpjA(Pjx4u()Nsu_#7X>ZYsC{imi?9VqbT+hfMa~z__m!krn>soh8Y8Qql#kvO z6Yk)P%7`}5cRq}Gq(fQ)88@nWX>M32*1s!)zH7j*QMxu7v!H}%Twe+nbYTTu6N_t9>JbcKB5&cYdCaKbY_Q zG&Ot+d|^}D>=cDGo9R-Y-|>%YWF&e%h;((C_pQRPsWP)WBWqf^5W<-w<8fAA28!8K zIR=VV4(T#bOr`x7P)wB>j$$?*XXU|f?X9iocjT#ScEhU1WA=yBT2w z6=UBO7HIexaI&OJI1_0<%Qx#n!`^2S!#ayAlwyu^^Nc|Huw+r+#+FE{xJxR~q7YR0 ze9NNk9YN84f;Fy^{waUYL~mVnF4?a-H@fPYYqTy?CM~Zh`u}cqVkR8Lq|X>AT4icV zF^Gtr=#-YGNV-M`U29E?_&jZn*h^fSySlS|tu)BCH>)CP?F}VXZSwA)sC!*bc$Y;{Ki`~ZJe=85VZf+MxqTyZ#TBLt!~Adp06}Zr-N(*K7J>@ zU6XI9)}JZu5)IlIJqv#~Z32YuDHynY0;RPTd)(z)g^h9CIBRvRO{MV6E?0x`3maf+ z;Y`NBYr4c44~OfRsi@kx$VNw<^4Y%Hn&pA;C828n(#6Y+Ayapp!E0)mH*G|GhYm>$ z>&Mzwwa0LFkdfwgnVn?tu?&SF{&bgkWe(PYB!9Ns>d+|6T(l`_URyJS99`$n5D$7r z)9e|Jz!={%B7;odIwr2gfg~^DXuBSc4)Qg%Bc`G&)~X9)k4!TPX-z5TkeE2@&WvLA zWR5yJ&ivl&3uKJl+I3-S!j5v64Vf=?=52?j>lg`=Iksmhv)Fznu>~2XLoM}I2yNCR zpZH)cZQ+zhZCPu(){HO@Ivg$B0&Dpdbv5CtKuy)f!6l1{uV{l}gq4?>bpow#gn4@A zADHN6ECGX8_^8v-tCW@b$)W8UIv%S8 zj1hU2noDI0kn(ANSl)q4Y8_$$@l3fE-6T$ny%1o=x1@`{(pk#NT$!Wqgg#PtOIwr9^WY;|KD&R!{gwRUm`DiSV-W=gj}Xs z&b+?j7KUTOOeix`AGJ-@@czTBxl42`*IU1%_7OP+~yy7rhc8MG8`arLv<%!R8%ylsJN)4 zsI+Kq(Y&JhMP)_hbBgB7nNvKcWKQXvxpU^tnLnp&PI+-r@toq~;*#Rh;ib zxutXG&Yd@R{@k*;<@1W>&6!s`uVh~7yt(t{&6_{3Y+m{NqWN>?7tb%5Upjy8{CV@| z&o7%_URG2#r>wZFq^z`TZrQxD`DJBg<>jDQPW9!0E~i*INzzvNbL{Dgw(Hy4*E6{x zqZ!*^pYP*+)}(Wmp3?HLZ!BUsQR7+JVN8U)m7#iS9zBfEAetgp`Zv@Mb*Acut{*z< zgVI+`j$i;m`7^`-i)UvHA%Mkc(jlxw_+xYy=@e^e;~K76SrshcsQ1oa`P1n)vYN>k))+&LQ|U|aYwJ~v=wpj zlVu?*o36uku>wfzS;(HTc&Tu**EPUf#}v!$HPR?PnFv={0SSSZqTyO_I!KgsF`vfs zRZ)p+D(W~?VA9X*^9Z|ma7#!NK8 z)4@a>sEDWzi+Kj)1vmCC*k6%rg&SlA-{@LQxG)$i><=_FUOv)7%HLk{gxsQ0R#H*HaB%#VLd48Ck#x8p{qh_TA zHD6zLn&vx@l~$+u4rZrmzC&4Q%Qas=X*AWwWx3`%OxliVq;*Og*v$-$MGczx^mXm6 z(X|qne!rUjx6^OD@y4cAG|#HM(QaR7v~haSuk{47(yr8c>N3-on|v#?(oDX3()#JA z*&7T#m7j50qN`^|O#HjV>m+VyUd*HQH_|4j(@G?*;MT0ZDU~$YZ#3b!R9Wd>%evQP z9mMIKZNOUxpW+7KiNsfR8TE45Wra9lIJ?8nV2!fsDK@*atFv)>(HsF$Pue}{G{s5M z|JmP(r{`IdOD9{C?=LufT>pfFd40JZW9!G%Jpqrdq_As2uC*YVYn3&PwMv$cvBngS zDsp`?*ZSnEdDi^p=Zv*Js6Dg?UzCQ-M{u++!7%9%mKaIr;FU{(=tI zlss$7@(I?I((%@m;z@@K`j6|I&@sOL#I}5^?cL)T7o1=!plbXA?dEMqph(Eg$k6NlV{C&H^(~bRdC#!XXR0sdwH&PF9U)H`F&I2(B&C% zSALF_zjWNeu^nTIrk$8)ok;n~uevSI-h3;sX#(ZPTm6-ml?!LTs^u98lE)&CMIMVh z*3dl1z@xv)vX1g|@W_n2JYy`+v*Y{6b>!9yC8kXpV@-N@f|dX4d@Faa*YYi9{J^i3 zuf2&J^*GX13Hya)} z01p^`KjGN?K4r8uW%s0m1=5!}qpY0eldKMAes}QexQTX8&9kPyn+rdWqkrC z4)mAzpXawp@+hCsN4z^$dKOG%SMp}3QD0`g7PO{bi+U~UmHejPv+;A?H{QDM-SO5p z!0CkD$M;V>=;_Pvm{2#K_PC}^u%3C~e@zld7_n&z1gg$SFi}NBX+rs;$ zW30U5F&(ZPmzA@Sa>5tLzlU^B@%Rqc*iqJ4*F;PEd121sQFYMj)LiS-S97cr!E0g@ zJWsz^U$(5x{Jy+dXd<}7vx+xu81mjF^*%f1aL&O|Mbl2nvra+3oUnJiH7N@JfpaeX z(Dzl27=4YyL<*0?02y)D6#AqT-LO>kLPvi6ggV8475JZ&XPtx`p460UowR(cbrS73 zsd!4i(KD0aqlxel`sRLH&rHs>CX;tEc_)*1axuEclSBJ+rTz8O+@maabc}WQ4a@qs zH!bVdo27lyhuLYa<8!U!q4n|5`uL@ue)^%_<;}IcP2(-^@;u91I?nPgo!D>Sn?sPrM$Lrtj51WT9d*w?=$0>Wn8CBuuh?`PNB`G z(B@N$3lC4}pL}pqAN0%Oy}WGRn=JI60KLaUZ|qSg`7an_T>wsb@SXCa<{3vG@|Mys z^oip5>KLmaX<3#0a<@vmvAbDu`ejHSS8h(qZYdprCv_;iCiEJ7-^H)qhL;(4)#X}s z@P!8+xA~#Nl|RPH2k-o1?VUOUC)e6C)@A*H-#2YIS#hB+b=C0+_Al^r>dK6}CXBHr zEX_SUrXL%Ntul7$ILhT)2lHIkN#kAC-xRjkCHj9zx@$s?H36BJaA&TO@1?-Vv@cQY zlgKJGJy_tf{>(3Mi^I!#L(<^Oj68;J@Xu28gwY*#yT@9UQ(V?f{Jtr$#^+e$=|_ux z%t}}O%C(*$Uq8P-t=AeB&n#njcAVkaiDRsZuTp<>EV>3do`6ryZ$h`=Pkp?zcxMfJ zhs&IiS8eyI(H*1ektxB6e)OH>vd-jJFR;90EbqJY?_OhvC4Dx(R(U7+U(MHe3u#-l zZu~NyGvirh;Ll9>t^%=h6Rd*bw4GD9zs5dJby?S(3Vocq(EAd9&^UD@XFZ2~1j~;fTTMwS&vfk#`CuL3;W1WDHa2!698{8%RLw--#@Ur8g zXUAogcWJ+Ix^eO-Yx148UMS7Cie|g4YJTT#rw-1)T}&N|@R|I-Mz_$G{JnyIuI9Oz ze5I0)W=omOcorP-iK6&x@U!q;QHcv4b6K0zCP53{39k#^Wxuns;wPRw+8XDYZaMxb zqNRTlOcWbI8@<5s0>@iCv42aIODv2PnD4TF#!tqM@^@01%bLN@iBDAfZRAqQfQ=RA z{bqh&vCAyy`EGt36;v2svzhI(>NW=D%tR#X#D!GQ<6wjOxd)ha$OU6S z=Wpc~c_wW~M%sO(Z6WQ!jI{bMxvcw08|m+V&I1~{{LgtnLx=x44`}G%yW52Sa~{yp z;eXBp8an)U&jaoqRkzVudk*WO#ANiptYX_+qGe&m+CnZnzAO@zHCM~}!RWe;tj;&G zDiRLLd4je@>TWOCsxQ z)^l zu4e0ayPouF)MrQunw4Y|upxm{9+>12(?gMUY*)}t?Uwa3yA?}hEvl93Q*>bdBC}^( zSIhoJu9+}&y`+&2&=tFf9Q?J5offQ0m(^v-mPUF|nPVEfv0S!PFJxP0IKcLI97gHc z%nO#5Dnsm($nXGSR)GnmGq_e4oqaD_d$O|RHrge*CYn1hrN`@drD(AN>>l~r7 zthXw0exmPdIRDVm)zank{ns7bZ65Rg3VhNxLRZ2b)mWW~6Z7#rnQY$CP4m6s#3a z=R^vt*-ym)Y9y5l8O*-2l^O3jD%E*;qybZ~nw6pr={HN-;s4bc?e}-BSiXow!LMhe zi9|U)`*oov+d7OMiKW{QU)ieEDi=BljhD(XGs|jD*9R>`798pMg6M8^9;%yd=HInj zUnS^rA&6a*pOfmmU7vwbbwtdiWnHfPVeFJ;T}X)(<-{7O>XaSrmi52Lsr+iouVsDJ zNfBYQ_GCa;MzQMBSgT1Bg@TNC3N@-D2mxD}u1VP*nC;uxZ2e?^t&!yhy8|~e(5y9+ZKz%z_a-?vKl`FN5HC2 z=Y*$>UN51hg&WyR6IK(YUWmV~N$j|FmxBfDC;FRR=NVLU#JVdDRb@=~by&0PR!Vb> zH2py^!dk;5O3QqaeuJ$lI9L)=z>&Nie%yM`q=3#Nv1 zg%4G)*C`L|kQy9U%jV4&Y%FRG5>|l?MLWlUvGScX^&3oLCuzdChF4xt%_T_DGip=v z!3{aYUdp*KvzzBE8_u$goI6=-;B3sqX%Pn+r7cw)=HeJ52G6=B-RczQewg8H(Q(SZ zr%PK?o`S(@fclIktd6kz-o|yjjfJ`za*|2U7ySqLrYwS*F!9sAozcH(ez2^o1#77! z9BOaBKE@17cLtuqD@)RGH5lg$eo{bDyKh9e4xfz@=r$+7)*`lb;wg9N;kJ_bvzx>M z{WWK4w6&_CgM$gOQ&jdtSbvu^gOcM$*0gbch^cxvZ!T-;jB-w5MH}-paMYjOE7~~h z*Tj*fl-gLt@mARd_f0qCKIZGnozGg6KFN1~NC8cYmBEoX1E zzl#P$5S#s@NJ1TsT-> zT(fjZO{k>U&^(uYT2!+YnpYR=0Cnp)1x#{y*(qf2>>8 zeLpEdbEnXmk}}h!tAW5XsE;{Sw|Vda?ur(xVwzi(%-z=2fsi_ofJ*{32(1PJxGk03 zEmO^usn@@+-%m?KlaXNa5SzTNTfHf3T@^Y{%O*2Y&8!Hl7Pb3)eLg3(FYn;jKVGwm zTKc}v_n!N`-*dh{&bjwp-}|)$J%IPr#t+-Vk9dj@H`YEQr9ke*_kH?EZIan_+nx6w z#9NHAg5bJ&N&=UEc)#b9d>`d9JYP6|jqkQkPVKlD{fQi&Q%oP6KYT=P@Xgf?J=ONd-C%2hx|L}?6KOZ>tqaT^7vgTf<{C6w&gYm7`_%Hs9 zH}!wLrU~chJM{BcxHCQe1c_UTKPjBme?nz{JcjXivEyy8zVxSb|M+%l{5eKEtB2cJ z%9(NEcJKIORuweQ%elt5f=u*z1 zp1wt2YlCtf%Ed2R-*2Y--Uj6cluORgH`<__kNKOOp)asOxsZ{&oc0r`z+i(|erRPMdjr`}%od8Iy8pYLb>X5X!k_g?>{KF;y&S$}_)=ap*@YdNof z&31-z$L`W{o~vuzu+Wk@j?cYE%i%XJrazR6P+v6t=5j&m>)xs5@HFW3hx*#Q?yu&Z~utachQtGY*1g?5my7{WqeVEw6mk zcanaw&7%v&q0bXc_;pU+;Qg@@mL_Ptkw2 ze2LM2z8ULAi*nf+^V~K5qaC*KDcaHdv|eAl^UdTzn)9v8@!8hNHuKLWXW|>=_~P`- zC1)K>hJFsS-xTfmWs6*sehE>Z_x~Xij|}b2Gf%zt8o3zbmZ2Pe^J)6S@dem#pLu0F zZ~17)E3`v@2l8W;#?LwG+crbaPyao~e!c69(N|!q+e@xsI(I}(yvmz+P@nDm5oJCX=oedjv-IACzAo+Pa(p)b4XCfj zer@@jq`sr{vrR6-`1YyKcHR%okTdyGV80{gpDmxe^k0_q$TrX8)Q2}h$N$f6xA@Qe zzc-*h+x&3pKbxGf!~7q*mHxA>2PxWNlQa7A^k0s4*zzSveJRWJkU1ZP>6iWtdoz?v zQ=cubM(lUT411&0*P=dKz6>cB=lE>be|clajP=jl&wZNXv&A<;JCf|zw!UN-kL@$& zN1FMPq`kKDV2b)GGuGWK$7ho>`4XmFl8P`p=dJDfXM7KHKp`D>vB{Z! z!#vMKXUrpqcG%>Mz82-;T*qzk7@pGWXyG1>Hb48!d60fa^@-^ZuQv+xON9NR+Q9UO zayj}rzsaoXXv*NiX5@$ILaZ5`?{z9%?7 zn_SBHZ^k@NuwPUz7@zlTeu>fEn=E#ixWyS?#rbBNA5q#dr2lN|Uz6kOQJ+mN!SS8s z_`GuFe6A>WoPP28&%`6ke)IQezj*Z-djqt?&+&QJHKWf@zuY*(-VWtD)Mv}9AmiJj z9q*i84bEPV=V(Wcc6j4!#+RTSCufW=LVa=i+1s!2bH@0EdFox)Ouyb?+qR8f@BSX2 z_lSFT^gpk^SMW4%{-)>quHhHX(Ku*nbd&rL;P=AL1M7c(GuW%=O?UhH`)%=zGoIe_ z*6^`&G=}q#3iC25q`tj=Xdq@90>+iS4)6aMYJu|QS=>Ls)p6lm#;^)c_ zo_M_FH}M6*y|}oQnv{9qS8)R*3%(D0311Q(2aoT<)%~cYIF^~Ht0?sq7cW=pX~+nk z0-cs)fe&7Ra&qAFz>`-gwGDLzyTGSVO>(F3z+E3u>L&1$H4vp1;#SlyJc@R~KLb4u zezKmS)H!TML1-6z4s;59A82YA3f})ArG{u1{8!L+)B&8VM<{g)hrgv%1nq)b_uvgB z@RM~2_o6L)6YB1vUGO`gg6IL7+Jb_A_))y0fOf$npaFP1bEM9@8TAms`+=|R#TZb( z53e7pdv90jec-deeTPxD1^i?^zC7AYy+1)I!=8tX;KQJk;03<|`Wkq_r$DE{3!Vav zzzbsSQa;oV3If0U0PF$Z1pekj@IQDwd!_yklmd_E(bPvC#yeBs@hq5n3M93M+Q93N zX_+YS+aQs_I-+(zqSP_)cqT|a1rj}YPD*|7Q7wbHuKp1;)(^bnG2MfY0RQ}py4?Yu zE+C(!FJSWteXQV%sLdn#C+i7HUBTn1|L3Az@JUby{A5i)sTKIw|A9P5yWro00;sLm z1-}13wazFoIY0?3vC-3VU&7wUq)gxmw42Ht!I`7iRo>%OaPnXCmU zH39z#bR05*+x{El1n&p_5ojDcVCiM8zX|-E?_r)oCJy`-Na8hF|4-@yeg||KGJ>yw zM&KuF{z>h>KYkT9;y)(AXFw6~ZQw^<)Bc>S*C)09Of5gbe*On^EIn>`f1Aej&pVZ^KdK+rc zp_ZNCj2*CQ7@B6nGAIwXq<1rXSQ!q1sMbIp?6Upcpd8RiOgiJ zJ*nR(wfUAIKUt$sYV}=-`guLH3+@4(0WbL5px41q*4LAoe199*q5=HtXMg7=Wr65H|4lDhCx-H!K-)R)NPogsA!BsqZhhSY~I(=rb5dmw2?ArSQ$km$?; zzYZGb3~LlNx`CdDL>pv4Y1y z>Jg14@P6=3;HB4K9)X{%!#7!@Pipl&u?w{;AtU%CC=Fil>!7S0J5i@k>h*melt;VZ z+kO>!4qosAPzSspc+;;T&%ryuzXT1zOAUAbuWNq_UWpobub@2yTn2?7)%XJH;T;3t z2fpW8J>P@CkAcLWf>&OL^#?K`;1i&y!Jh!e7BB|zf_H!<)&<~`OMVF4xm(K! z{s#F4;C}Lg_mO`9_&iABBDn2(eXL-Ryx>8QjPnriHS!~1{s!bI#wK_YBr<|8kRJlC z`yl2AWEOxKkjyW^ljK{#{U1W#kDzJpjnQFG0tLCdtbyQU~mBjpkV?wK) zHI>FW34EXyu0?9?TCdix4Qj*MsD?%da!CECQ*d0T?F<}W(O*m!Q^ia%Tg(*;MW^T% zTg85HPz;trrEn=yik0G}L@8NHmolYXsa@)nx}`yBSQ?f5Q#r;KrLF!)Uq|V)~vN^-CDe!sHf|hdcIz$ck2Cm${o1TMy!!+q#Ef)q0wwa7F&z{ zrNB~nDYBGW$}ahq{mZ%K{_2#f*(|3l>$Wic1pcpPjiqT@cm?);vwd z+?X48({9EsxQ^R)JMh`i^)~{INFzG-T&|Ia=URg=VP;$oEE4k}O=1Sg5)|#B{A!F5>$9zFMfZs_kmOI;i?;{_#vp z)RM^B+&FK$n02F?st4<#daNEF=Wn6z)Z575L48>Fy8$=iM%|>Fa&vCpZMrSD=k{II z@HIk>a3kJGAU54bVzIXnWqv5yn*@MtBo3LpLK^Oo?y{{p79 BL@xjU literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/error_wrappers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/error_wrappers.py new file mode 100644 index 00000000..5d3204f4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/error_wrappers.py @@ -0,0 +1,162 @@ +import json +from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Sequence, Tuple, Type, Union + +from .json import pydantic_encoder +from .utils import Representation + +if TYPE_CHECKING: + from typing_extensions import TypedDict + + from .config import BaseConfig + from .types import ModelOrDc + from .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/errors.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/errors.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..387cfaf0bd8d2257bf7b39c9bc40f40840f6eb88 GIT binary patch literal 184320 zcmd?Sd3Y36^9CB0fd~!(r4>;iK-feCg&+_D8Cjgb1aJY7MLpn$kB_kF9nXL=?RjNG5sKd#Rs=`*KJRh_DO>(n{j z)05HXk+?E(adBnwe=ryqmxsUnFHQbE^FQ&W;^HdRT3jh^;W=As=auqpseQw+;ddpD z89Vy6v4ch?4jwdW)acB_TZSf%%^H`AhadAT)C>Phab;4k~?`T||#EPXW)sFie6aCrx z^e9|vtUa`n8&m1~F6CJHi zSt@hxQS^y%aRV*kXM8*?eejAjirOcCX8H?td2!Dbi`;7(nfKxRUB=%wg}zT`1JqR z|9Nx!CB=JlM_qYT$|`i zH@5{1Km6x4k6Ik#$t&~HLZ8<(`mQVuLEC)h)zyN=zEU8|g$`cmLp9dGY2M&g&`osG zEwbpmUULuVGOr~~&dG$CZm8$;yY`h;reM|3=l3P0b!xuChj}M@{l>RlQcutm~N6j6v`7ySuQhj9qs_4p?4ekt8zi zyyiJU<3zAj+~V)RyRch&_UY1@W4vak${6e>rRnYk)=={*4hO4d;8BJ>e%JAH^`nMh zL#e_tXuL{($HC8Mx~JA8rMm(Kd-6s=Vqn|aQgO{!6c8&3wWi@;Y61VyPboEy0j^o# z=iW~z_>E&_@P|rP15>Y=dIk6`Gk}|dTp8$2l8@OX0-)f9_ea=&YQD0 zv$8k4aj7iCO^0|&?a|CQGt8qt^Y@_9N0b(2Duihn(_@H}@x+O@`AJ{ykfbzo zUxs-bkTWM~IyeIq3DXwfBHdh_k#hiK0*zPXlL6Jz&8;?N(3pjF#A^l$TjA57@qo54 zD60WXvwJzibgRbxw{Vj;cbZ7B!n&t7xW$`uIAP{GutvO$F0J$$eKUmAXRf1)iE!+m z+Y#B>uSjH)}(AR6K&IJsM^z1)NWll&puVERSKP@a5G#Vh{fX+k&`z%WEyK}&9u?eA`yn8_$ z_-a+DxIzR=a@9X!wO~10i5o=;M#NgL3CCCw0iXIz_%ZC~f{I|nz_9*HyS^v$VWQW( z8Z3T*de^Nl9oKxX*WBVWr#vDGuAqXSP{Grb%J@JuGq3buNT265n;fi;X)oIdMGKBd zrWC7y+YY!o2BQzi$UJHfpC`jNb2u}ZJuBO^NFq>f3)p=Cli-CG^X9%~d`G zWDkwX?A3__`uCN@WW`@}JQlNF!wK$hV6oK2`;eOHtC5AuesA_cEV~qMrL#r<7R@T*YsjVcXt3UZ*KB& z{(*&E09Rq%pz$M}iWNDhhJ^K&!2IWF4n!_;;W_v$-RvCC%x4cUZONhrPMI6a5*b zgGTUIlE~-*p5-k-;xm)4z7R7j5;li3t9Y|V#z`;<$gE%rtu^+t#8_-3u~^q@+Q2Nl z(3?93)*GK#*Z?BFz5u9LULW!@U=hFjHl$2X-u)61y92eCGbFfRr7=ArhcGS>65-Wq z^X7tzsAcWsgumWgUsC+_H+p&^NnvRmUX2mZ`spd)nOPCsvR60r^dHc76_>8wOics1 zDhy+CYUo3WmWZk@t14om19Z!O3#xT$ezIU1Oxb(`@)-=}(==2CG_^?cHfRb4gCHHH z3xcDvH)n&C5g)Aa}VKI>;cU!6SbG2mK%+;sGR$WW-yHJhd$Bm-==HY*L2#r`NpXDEN4T zYYS_no0t4*UBgb>f;%<35~k6&>1IZ?^xXc{V5dyCH@i`(tn$ETJOYV5L8FQUETb{A zd%D@Ja(e4-iIWT<6(~ULT(aKl_moP{?OYiJj=5dxh5878`0XNUpODiXCJ5I@1!-vJ ze}kzO-kbk5|6~P?PLu%wm%#Qfim}#v&GQ0pBMVV%&}hpKqq3pb^dI~l9L6vm$bjt~3by>65Q}*E>3q~B0x1j7m@~pFW?4u4094U617WfN z`N)&UV%*#r_+v?_xPn`tj)EYq7nkQ&KGXHkW(1r+wefesU`NyaCl*5H%HCe{3&y@3 z_9K#@!Qu4m@rl(u<`$2+Mv#y&Yo&mpQ_hA?=81&oSLCeEZ0ZSaNFThiW3GDvd6^5> z9sQPnxB7BNRrcj#Wm#7ap@fVxY?3c`@W2c>w@iAlyf1fRZ$K-vtT)&Rk~VpB??5WLV+{TuA2eDWj}?QP0;ez& z3*8q&*Qcu>3o#lzOY7j2pkNj*qhXA-tq+zPuem#DeEPFJtE{RR-X}b~9)=g*869+3 z_jes*r2pbg=vd>fg=Djx=r-MlmeEYFQ%~KlbOFP2$nbU1Cm9S8-3im)ilq~Mp~^M| zY9As=c%_)6SbkJKwHK8F=8wg>1Tjjc)b>zo@l;|9rZnA;;M@i9xRwc)_ULG?34EDX z)P|m=iJYhbME-RYwDUmgSz3j<2FqarUhv6~T~#-*0vC_DBk(vFrJH|oqhHy^a4)Xp zK~&Mev?Ky63jkDBDge;9fc55vtrwE7P@{^=UfpWI&8%yRsb5h4+^**hC_8@knZG%X z92!aZu3_9@M};GY^L1Z!p?rRIBDW`A>}e6BSUL+`vVuyQY>L^^Q2-hS+oucZ$bnh! zId)i6U{*3ovtvJ>P6%!TU6Vx)y51I@mzmT@0(f*LafoHF5J3TI=AsLumCSbHD3c?gSmD3dgycDo@vR#vS(Q{K!56kR|r{ zpAZ+5=;LnQ?7vE9-tIL!b1V0u6y@$Xu!e@|91d1IRd`DlY1dqvd*rD?ck+7}{19Y~ zD@l+IL2B^iZGo5f$8v!RSvSsX-%#lanuHmidvGag%+_=J$XAA7LTc2Mjo^4ZP&QV7&MapE; z^~#S>g`10hNv-JdwD5+;xt-ZuFtM2W)zeGYaaORX5kf_*TZ-6Lo|{8u>@Y?O)|nwu z73|cCFyd8iR6IgIr!L~ijOfI27-}Wa>E6^0|06}yG`zwk4t`=M{{KmVo4MMb~ zVQ%?tIH)rQv37$SUXJbkKWPWuT2#nS;h6Jej8w2q!Cxxa(}mF$>_U8ERoWHuJskIi zq_?OFwgY=sXt1+_t+EYi*H zm7DKPZ{1x=;qo|}LV{>(mBQCZDZE=wkS`X1WYuNNvS1ybkQ0yUFubzLhXuz^qbMFl z>)j9W`FG%|aAN*&{uvuI>QfV|JicF4UC;9PVPra{`k+w*AKI&+>}R=BnC+~>Ddi?^F%-ytP4%f?9u4H0Q{bRS(%gqqZ|5x?$0W6xVm(#xC-=g($4{QWW zRxh6fC#jdOK(+ce^>QU1VQ9U4^Z*6Nu9vqL6cx_&P_$mYhz1JP%bO6~KC|AOH~A;^ z1N;dZ7h)ozs3x-fuFL*Ete4|4l_IIy+!R=k1mUQchnGXnV<>o*E+7Dksh2O6LKpS& zi{IO`l6v{l@bLEumss`kyh99qsh2yvLEBsP^37-jjq%hoTrYo)lY#u7M4we)_g9nvlJL8aF`d&Mte4+>tEdeRAy<81^ zv|io?R#v?{7>xe?dYO0C5@o6E;nh2I>8x*m@R`RP74tc=bgbn$U2UzE|H2eds$pSR zFO_c4I3F`Z>=t@>USYVj#p7`dl1e$tTUZZCz3Xd=CAkmR3kKCnnSkM*#~a)PqWUPO z2{<9T!XlC~8Mi7n!NZeUVqIM?aR694?!HOYhsE{)?qdhOHmwr5QYFMGt8l3(u@ZUB z8H>D*06>ze_Rv9UXouAhH{&?2WR`M7dCfwC95s zdL8EN6Tf>G5``xZk5|M6Qs&#Id;@i9z#@Sf`Ci;u;*BZUBHuUsnR`vNkm4RE9*TKtBB~`=xNK=vmg5 z1T`gQ+#RtFgev4+vQ5t&mKYd1g9D^q9R;UuuJr_ zz~JC2`hG)@ z2geYA8v$|}9KI2-0b%3Gi-X;GBcSmccFi5dA<7m-wRJW71}bXJ?PVQrGQ^_S0UUd*1sIIJzmn?gnI>kq=rK=Xp4|;JEOIEhO#u zthB@3Y(1z~a8$b8??NJY{|=Y~;eDx$-`Ff0IzaDy%zp8+%= zZ1MwNgZxR5Gg1A8M1@+NTX)?@xI5|KnHWqnaO?gv)*KWXx9|_=6`81Jk>8u-$3#_5 zhj&-mi7LCcEqfSgUjZ$q(UEtV{qFwAs-C=-m~G&(d77wvh?3@;1COr*0d5*g($8K! zP;N@x+&^M-7qOpr=Bo_zSmcI&3u6TNTKog6y}FOwlb7N2BY!iE*F)mL-q3fGZb5g2 z{H^RS%YM`S1OOXKSD_94hw!SEt+?qMMy|U!>Ib@{2<+vw4d}1-I?-PwSv7*0tV~cL z|8uf=P}oF1mJl>*3!UUD?&*KV*-HMGATJyT-mf6^eb%1-C}tyj`hDz8MehZWoWWbu zNK>ELynT1|zjV@8jQYi#>qr)}zrrAZMsrTMei=2- zL3F1@RHS~12bzjz6McH`MxikS$a_0Kw4oE>3SqLDoPGHjW8xP2a0(jW6 z7tpK^E>ZQ%L987J`^$CkIHJf(3wzn)cXj2TqG{ni@@q+cObb83T9DmJW#6f?E7-EH zC2dpCLa!z~1M$1>My~ecwPRYC_|jR{FK0U6TSoW!jjP1KnEq@Weju{n!ELVmUbJQ8 z`CfbJw$edw_FLzB4*)4e)4}U-iz6M}M6Lrl>dfbR=OA6iNC(wn9xEM`&mRmnvCj7l zAqwS!L%98xe=BKuz85Eq^?dIDrXsmu7<-BKI#^Jw^Sz($rzi{U!$AO>JPTI;0PRcR zV^3atMf>s>&Km8j_dsk3&i7bvIG!i`zr*`rDiFeZPi@7(`?JqDpgiw$42psGNzOuK zszp=;@70(Hic}AZ_p+UU_okCAyuT0M{0-hGLJBaqn$R=df4wMppN-{K_A6iQ2Ik&j z2t@8zP9RwWuPd2SFTxt+$?HtKn{)pKylV1O$R?om{@rKgKNFtbqD_x#rt#Q z=OsVlJwb=}R@sj}C$cZKW#36!4``uRhTQ6KpTsKU$-AC-fA*Pw0q^_hKEH9J7#P!E z^cmV_@-`f{g1@9BsOT1q#I{|s_IYAV+@IDa)u*nkM>MS|l z+rp%tyc-nnUq5x$ct7w7#Qv9f&!z$)yk}`E2HuxE=D_>fPcbM4-sd`tfEO*IB6x4b zL{JRgGdlwB-N#vYUjyI#4c?!H6yW^;A|1G@K?VE<*HOXyU)zAWl?;K%_1%ya(0#KG zevL4(@LrKUe%C~6$&cFRzeRqZk{|J2ONS3r*)KjVvfJ3Qr;>IfXrWhs?*0AlmRPPl zd3}lZ`Lq88ydRE)r*YJo@t!^_Cf@tNJR!V42sW|s-cyJ|c&|^9 z50RF5PZP$9_aqPs-e<6vc)tay-@v4d+?F7#(UWf znDu{&_m|g;6Rmp$PiQL!-uFJ_!22O;9Ru&noJGJ&i>L_RdovLfgZCS*1l~uFw(!0i zzWE!xFM$-`y)2=JeKHmB8@ps+tCq4%sUo71@1k*)NjzOVFb4K5pv$?qyhoJb8Bz@0(`+3wWUp|xn6$w3_F=a)IJ2;Lu-ZVT@&_FH)01*{as`zg4^f%iAa)y+|7#`{f= z#KimUFi!~YmBA(!-iHcN2=6T^@_f<~?>&UE;=Kh31@8uXiTANc{TANai{cjEF8~2- zBIh(E$9q|nLiqNk;yuBC)_AYF2DAPz@&5j5aiWFySG5%b?}ZOI@P3k7$H4nmXA$tJ zMN|au!x)vt;C;w_!24t%0?wap; ziT6&j0=j4F;N8q}7T#0X<9E%smi#EZ^LvYnN01-!-d%@3h2fC>sb6H@Zp(g`v_nCQ zK0i10es?)!22UPVo4CNqlJ-iObKiT4RGPYCZ%gH0^FX9-aV@0}@f4rz(^ zfx=kv-Vua?_qpsP-tR~1xA5K_@f13*dmaR^iJa4v9Pd7qLiirD;=NYxS>ruvB~IMKrU2il5(_do7;;Jq9JB?jL2Ig5aAI5iLz!TWedWifc4br10V@NE{}3*ei- z!TVlF0p61cJ?xXIfZsSN8&d>)D(18JAVVM$?>%J&bkEhn-!scuc<;&{ziSDQ$&aG& zet0?foghEreSi*s9m65}n_Q7S!Ir&}v`0XTzUR29_q#hIGvHg)#Czcb{{r4Gr^)fX z1u-zDUk)lDwrfFpzHxpLyuY)I-4@<2WWR;?lfX(*yjL4WaseN2&u_pExZpvJcaPy z5CqU(&S^@H_ZcXK@LhGqd()h=#(Rr=sPb>&eKNDTJ_=|(^TVYj^7+B-OT~$Woq@oh zu|`|gAbiUa@A0_I%ddkJc7YAcO?H633Zo?i`isa}9{jlzZXlfHA;KRyKMVBu1{)u^ z&<6?mSkGjJXEDIP_)-9W_FxP6W8tKNOGSAmkQCRSOYr3VAbf2VPpP}dK}dSahRkd6 zl7TFIHPYRZs`-ru*wo3fT_sG*dep>I4T9?nAl&azIlqwzGWj+*^h^}`3rN31p8LV` ziarxhRBa6upk1(1K6GbcB={^tI)VJj4+_#Bk?k;Gwj0VV9>u_m%rZZ*jxgP=bnsN> zR*2-oKnL05clG2Sd=!;s9wfg>2a%XC>}J<(mdt^D#T`>p&k z8`vzGUwF{r$S=dm^(~G%bAGvKTFm@%DGU>;Cl-KBto%|>h(h`0Bu;Vi-zP2e%TqaI ztoh|QrXu;}1NJh%T#2Q|$}hoND9YMDECK;+GM@)RCC@MYu%deMro(4=x@X&zv(7I& z@*wu#$}i^#AkX}K@?BIQbUrv#TQTa1`4b#jW6?(#1RO*^-!s!$bUbPi6{#m064u3} zl>=jtR@x7+(n?%aMAMm{?=c|-Xxl;1;r<^L!2Lhj2qWMRe+abw$quM8d{_}#sb6Fhk{ zi1cSCl@RIrkaEfJzK`z1{Xa12w;;XJP;~5-sfP&^5o&1fO!A<-m}L0frSwJU*bKR3WV^UrL7ov zUvjqt?`uE6pcr^RlIb9N(IP5>_f|{<#o&E)BJke5uZ8zq_~vi${w$;b?*|a+z|}}9 zfct;k-|&9_U+)8RISheFyc@Ctx^LFOuMs8|-YZH8?wV*V_EC6$i~OD-Kd$Vxboelp zeGD%$gX}i8?5U)k30mmYpN9y3_iSVaPu^R^`}_(20^X0%eYpQ82FCQ)zDGMGe~mMc z{10f$NW71hZVT@pvfsk{B4DK`-uJ*Q4!q}*>vE1dGu~U@8x!wcV4e`(KL(pvc<&@c zA-rEek!wgxyiXZR#)|iV=wW39a6uA_gbR3h4=L!fK4{>K&a$+{}T0sC+}^= z`%mM~8t=y!Kt4V&uds7`gUS+RDX#&|@Y}t>J_CnAy5AhHI-#f~7Fa2Y_W<1D!28qW>gA|2 z<2`+ROuYAjc|v&a3O2Fu-cyJ|c&|^9-AGHk_ZS_*Q{yx%e@g!iVRxP|v? zK>(ZV<$+Mi@qP*F2T$H|#d|RGtnpqJ$^JjZ`^#^N6Ycwd+KPeqy`vmZK18i!;JveR zeP3x26~TLNCW2z{KI9_cef0Gf-k*hU{$_n&0x7_ISwhcruhBJjmuyTC@HH@>#ZNK> zBG>n1SpnUXbnrUD#KL=H_Tc`Xwd6j+~G7|3(OSgsh4eYn@ zz6)3>iuY4+iv#a(kn5)$b!NQZgrJD=y#DPlPYCZjz$O;nhYC>$?=2~EH))CYJxK2M z`rZPBg7?qaOT3T82Gm;L+l%5B-oF3=Y*NUhnUdqZAL<8B9&R$So=>>*tnps;4T$|O z*Z22d7bn{H|FjhY?}fKJ@P3k7$H03phCGlgM}wbQL`CpEj8Rz(-gi_5-Y0jr@Sb$R z-{O4}qyX<#2|d%jlT`@r|H;M_0pA4kS)2$iQF!kpE1-L(4&KcyXW>1CJ-Gj8E%{M+ z|LQgHYes&=dv_iF6oy0gO)C3#TlTx8Z3J5M`MIgb{vANXTU?0uy`%mGyw{}3asN*Y zjOm}8hc@p2L3(}<+AQWWp;J;+VK$NK>v;S40d4@aFD@552| z#K8Lmm?wny{$LXe?^!|=!h2_m97tN?Js^y=p6>`k!TT-jCEoAH2GqiPcf?cZylyZE zpuL>alpODK-l6BVDc)<1JZrosy$V(SOT4doMVx5g|I=0sy#H~l1IpzXC^7K9Yovqd z8%_;GMeshJQCSS$XPpPUKit*A`&;nM->mO@Aq99(BJ@mmPbz@>f3h(}z^7t9i{D@f zM6T~WWd(H4)xqC0%UO8u${yVRvzGiQydQoU{5~Q-;(dS)e;vai`|}YZdx9-{C28LS zE&870rrz(K3m|&(P7&{gxBm-xznmt={Xa18{aSb*fOrbw{YMbMCUQ;-FKm-`vL|^47|U6i-YJGrxpwE(;1b;;C+W1cz^yH3-2v2 z{9C*iLJIKSg3!bByHvn$ltVU_{d)%Hv-nDIiNgC(SpnT|>)>CR})_ySbug`K=^qKmxpf6{r#9?8OZepf3V>fn_U2?DeljnFJuuJ>`D8;a}sxW+6V#Wh|*l7YAN28|XXXb(nT zCmiM7+1psY=GI_cfj3iR_T?+qOjm6h&yU|KXk9vMywAL=8ej4?+G|d%jQ0S*VqWuW zythbR7>w)Ecsp2zxekH=fj}puP`-~0SvQNXjF1;|_Gnhv4!>VOC_-y@^Sz$scXNuf zpeJucSMEq_Aqnoynxb8W_om}Dh~}n1au;?Xi3a%+?r9iRIH<_31^4j>&<%Vkd-J_P zqah}MT!{e>azLyXs&F0k@x=yP0(ClDB35Kg@GQ^82-t25@0&(>i|^`;_0sJa?+2ze zK^pbGb$z+^|4>_a@=77DJm&7e>cNs~Q;Nn|wDcmchj6Wb7D{Ta_3C?8@Xj8-?KtAi z+~NCS|IYWHsYK|!w5PUW3^;{|rdmWr>Z@v!)T7^?qThec zyaD;P>D5-g-N`UJ^Zn3?kb-=>S~80JtJ|P}-d-AZP z#0AVj|6;yfOE>zB_F`z{+qq9mzWtELwad#?gHa>%ZD;g{^PP(XR=%A9pcT!xZ^J>3 zd^T-&bPI39m=<>#UjkN-^xLP#8VZ0Fm$?246d7Y%Xd+dND_^KE?&h?Q>-!j@LP zeJ_pDAwu$PLySPa?axDm=#2M&lW%WF?cm9)WaZl%Za({b+j};YEMdOI@3UAh8p2D| zTrE#vq`ul}p!G)Sgc~=cqv9~X2)!Z?FUrGv?d8|3u42`J${!Z69&~FgpEzG`^}`cl z$3na|8o$)@rM9d=c<&b;bZg4D-g*ljlhVMb-kXta{diBkCowpbfO$Zp@0HF%42Ou~ zEFvr}2o}8O3dj8DHTK`=Algf#fKv~lsH+sa`Z*{*vM72B#b?we`=>Hk(&bfHT?LV` z-%s73JCgY=ZLMTJ387K|m7oHDw=1Q_`dRwS9Dkt4-2qb4Q&xtbnd5t{k;8tG9Tsxf z7oaY{!6k;f9{@2D?`u*NrSWG|egs+MGjrdP-XrvQAsKdBKK|^0{mws5IWYkA#TC?2 zo>wZ*iIOVaJNm)`ej~${J`3CyPv8u8iaXq8l-#G}{$4^}(NV_~nb63fX5PAHQ7g2r$ml(mY|+faJ8Ol>0v&5*D& zRzV8tZ%G18F#?IWvPHI;Wa&zF8S0`8bG4AgN0RL%Sse}HgNVbxlvcE*2(G*Y&j`Yp zUyS{c{4<}q(wluxVl~r!3)b|6SsyoF zk+Xrn_VGz(N^pbMUt=&&0S2$kbzhBsuXzbx5P{#f>45K}1M#_dMcukG2pznN^gMCU zDhlhnD)L81xO!xLr#-qI(cfFJ-m3pOoHe(ce2EauXcd&$Nibe&BqtP&_i@XJ-Aa;W7EzJvFPO?ad9o)eCh$Yt23K0bGR9DR)+EBsrdGrz`%?d^Yr;N?>}4_$d3k#cyY_zZLJzs71_puTDiRD_0O*|4F>Z zj>lV&ZDYmb%{X7lb$8^-f97~}`_C>O|B`WMvd7=X<2)WP#Ei!msJCUQDRK<)_m*<{ z%RNAjfm8Q%10ODDF@H+n8Ix0&RCfgmlnz**k(J&=6)H;+YLrJF!biC^RwAS3;jQ;U z4O1&axvwMl+!`;VH*mTcDP2LB9jP<(Q}Fx4htCh`=ihTe`1~V$e%JN*e5-z5%liC9 ze7*!ldSDSh7l7ot9%DuN>z<2O{JJN&Uh|?vrvBqIzw}Q1@sw0Uu5FN&p4;IlGF%c$ za9jp(`6yl`iOc=Cy!%?YUEv8hH2{* zY9CMz)Ye8F*IQewMUU(r+N!CPUTrlLx!L^PGRQkm$FP05hH zL~UIu)61@=t$Sqx*_E|*Nc;4MAzb6(O6bWSHG{kfVu0*Z_<;zt&Q;2z+FGR21KNsH z%Kh5g0`;I**>MM z8C_%!k7%p2Qcl;_CrUX*TUV=|QYYnpnxhqh{} zUA)@rty-sP>m_Zq($)c$&`euvRkMcLI%@e(Tkl!^)7A|ty|T92DP_F2Rw!khwl?aF zPW>hRyUZ&yI;yP)v=z|S3#!?EZIxD=?a|fd2ogb`1d?ugBoJ6=d;x7_NVW zP9ODWZHRp%EPx-E^FV2w8r%We)7*_moEGGabV^-i-XlzL+{X6vR)t#reCG3K~17iH^HC zH;R4(bw3QWl{#wKKUimR8M32LJg5|3-b53U1S)(8a;FI=*(##%j}Bq=mP=R^qh2f% zwp8`5vV~Vr;Z4KptyYSIoH!>CkhfPFsZRCQBchz@O?9Z(&!Jx8KUMF^Y>h*nmr?i~ z5Dq}>2TwZ=tKMG<97ZfuI_BSpd5|^<0=CXw+35=h%e&(FM$64r~^J;DuN;oetXKaL^J@ zSj)+hl#0Y!CO;Y}f!J@9W^wK;_2J>5#! z()Ro@`4Kjwb4bV4SS>;+gFgV`Oc}SOsb2JaIz!*UzQI$PLcyU%8RoSO8UJZJoQ`wdfXDeF<3NCIRR(6uC0mTG> zgsI1WZE1g(U|88-CX2FVnL;Ui9daKOJdV}JHtBwtBWO&}S#7ribuNGJ(lma7iB-!x zWx=xCj$14tEt!R@I<%C1#2MXQ#H1Oj|tr*%5M` zYWW%>Ky6vispa)iTCPtGYdJ%fzJH`;Db=zM=SMAfo+Db8c4&D7b_g2Nm9UC!%Qry? zkCzH*Ihh&Pt_%7`X<5git{PIQ&r2`A=0*GFVXU-5?*8zR#h#B zBTm(p-%HVAVI0I_FS{Oms7=_G-Tt|jt0st+vusd2Sx#)}bJ%hL><~1%sFruxDQgr6 zVartrXw}l=)bhb7Ef2H~Yx%mQ|9@o58mi@7j-(@xxkSsFj>@ZoX!(i~jwtR|dgj#l0E!VdSdwdAIh2OhZ!sqSj)KM+R zAp+EvC#0&dJdP*+B0T;S_z^K&&ilzC^^a`%>G;UFd=-@uvii3UEtkO#L8G^7`Ki5> z-U~w5l5N$pyHm?$QCj|dRanbKlK%gZmW@@*H><=QAMeGV-v|8p&K#)&OY+R(j8wX6ig*jkQ-U4zECs->Uq;&hs+ zmO0i|#dMc(YAHAH9dS9YW!RRt%OdrUZ29%wqUCfuF5gEghb{LwY`GbB2pYHQbY8Rb zr=n~b=g@Msr2l`UWoy;)ex?zc$gNub4z9K>>x-5vl(3N< zmj|eaX|xV$`5`72S|Q^&2Zt^DB!_KT^Pg+^c$V0*AJYi6ybZ!(%S?yIr$FPNQC+p{ zV8>-U)$(z)6+Km)T5_^ZEf=;3YdKyPsefe4!#2olY!<7?Y0Ds;VRfQ`V{@d$H@-l!Le<|F%fHXAKBm$|v@JSHLt|d!(F*rk_>k8< z_>Z2Q@TwL6!EeuQAcKZ>&5jbjjK9li?x*lvt19lMV?u}9Q&*pYpjCM|NDX?ehU2W8 zmwNxho1J?9_po!qv?-jhzs7xN$?u0JEb4Gkg$~ucX2r}arcA6Jml+>4TERnjx(T-; zeR#aW8{CLzbuueLJ^W4>YJoxn?@xg`g>I6d8{bc$c4pU8-dsEp+u@YgjOV?qTKHW{ z+ARB2kiQwfs-ZV~;;Fc-8FI%EH&0b>+!yF;-#xT`uS#!?`BU2?g7KIn_(LpAKD{pH z(0s4Ab&XC3>BkzqK#)}f4t$lADXy*5BcY>fty=40ewv$ll*@@fbA*l-K+GG&i*>QRq)i{?g(#!s3-nySA>8`jznNhHl~Y z9O+VAEiGP`D=+;Wnbc;g*XMgIUWvkMya#*^elC3Y9wXt?iR~2E5!iwAJH)@auBJkj z+5^c4Hg(>8#EqYjbq9p43;X)r1^Y2LSnp~`Lwxj<-zCJsVnNVoK=n*-WqiMm0`Pl` zyGj9+L2vf&!K^0qBZNMN&+tTV!V@27|4=HcIgI~;A|mq&-XhLk-Ow|j|0-|FCz%JZ z4tInU+#YhV;N%zc+m4avWNa$jtxZFBXLjSJD9%H-@F$CU`_M=X8W-HjVW$Lc>m^U% zXR8N+1)plbO{lC2UQ-?}z_SH-7CB+s%R+=-al4m9@@z-KG;D9E!wD8@=9ZwbLi)%x z^9sBp3|(8L3y+s&jaJ?r&7)4Gh57Sql%l&_>qOx zF_XC@;7t09h|C*<#`|RFH>%p~9}ly?4H4KDBQh^gIr~{t@}a!;_^>0~WIeiVd!$oN z@SY4lB93PUB7dxp(F!l?Z`31h(|owGofwK8)9tbqTa63&X&KfHQDjx&nurW1_b>Sf z;tigj*3(pJ2ubEiJQLFiztEn$FzFE(uK8YGP3P4~UOj~?{L*G8^N`0p%}{9KO<9>$ zzWIuRE>$@#_w8!u#xhBm=>CzV^mb-JBM=1cx`B$_Q^m6!&c~0U)~$tydzPQap|18I z1&%PG0z8ZE?t$G5lV?0X&ULNih8cJG6FU0Gm+~xYz=027VDrxa&WaF+_cL+&xvt5& zafW#|BIT8!3|!VYQq9Kfsm7jLu8-_#!JgAq@N{7i zKlhHO&QsSze9*X3wJyU7CoCa@)SrMF(+zN`^t-QxLdXC?qlb>DqKmApeRqzS%Mr*D zes^>~!eK_t&Wg5A`2nr84rhhX#KSd{?lFJg7 zd1VjDV4}+)VFv3UzcJG8y98T(C-;G5@CX1fAB71IQPe1nTIu+S7 zf<0HWXK4>U>CKRYH2k*kSoSnT4}ag@cpF;y?C%RLo4~$v(FY$6xtxGmk#6pUdDG1d zR0OUb_)J!G_deJwaA$Q=%8h?8p3K4967V!>qx<5rDx{m8@Ew>fcpeCLy^sU(t(ICB zJH_445zk=+C{8rtV|w_?pL@P+_4})Nz;_y{#>L?4Ym|~<9${9N-wTB#nbKZ-|I*Tm zfGX`-Hj^BZMUE@uN|~1YAUeqKaE0k=jn8yi?_7pyJ#$e=NsGbbWN^F^K5mraln1^4 zf*~-?K&P-RtU=dhlmhN^_* zkc7KLLcJ&n8%f(bwuIlB>Kt;5NZ8C#WmLj;Q0W}1h=f(x$Z71Vm9~<0cg2`iYGC=H zK@ka`aMX(!1uK;b`QaTo0vHq};WN@^#g>rVNawKTf@mx4;HdU0Apul6hYXPryftzT zyGVO}YzfU7?eO&AA`nOEtahHXGl+W| zt^#9G^*F!<21m$X^EvpqXr6?RnI~%)(Nd3b(32R%JP9hzldsCrz>UyRV-4qiK;$o^ zy`!jr7Uwfi&xo>d>8kuR3y%yTg+=O=b4Qb0ysp_@Ha4I5VKS;#3;C#wDVA zIl7}gjzufyFmA|$N*1h3heX&h-m|PChfc##D7-L991*b&zkttl!Ricy1qx8TIXnpl zmC2w(4B4>pU=BvKJ$`<)*z-BcEnfb z_((jv3SM$}b|ISL*}JeP1?FK^;@P2S!LzeT>^Hu~+yWJl=Nz7es1_7eRz-a|NE{5+ z>(oUEx9$|5RX(r|7B4IpG#u{-CWbJyC5LV(SJW!obQ90^w~ZQ|!qGiA+H{Qv5u||pRuo=A zqjD5&Thb}lSTfn^r*$kCU(8z>+HL%nQ9x|E^Mp0IPE}u8#wh8ka zC`sSQMPZO(uIJG}GwRh)4haI6){RhZoM%~A@@xT~cn=`NIpS)fXIW2nUMQNono1^? zxcU*6leoH`pM^6Hj_`Z5Q0gApaJm@g4m^+}BH>tk@>J?5!!#(=0BDeBF#)WEnQ z(E=FGCdLf3ZNO)kJj-q(-89ferw+`0^UWMi-#!G95=d7>4e!h0okWbw;OgafZ~aW% zyRBA~d)rAVr|zAA6sYd?;{3vq*`awqvi!LWMQ>-iyMPqY?sYAIZg8sP4Wlo-g-GzW z?i`>{yy3@ya&VCk3Qi6Sxk|hzV?{2_^f%+G4dOXkh}Eagg8m3K=@E zf?1@P2~49-3*y9j>$y+T!lVg|F0LwTSx*a-dM98Pan(Y^V&HqsMTE}N!i4)t2tCTx zzbkX4xj!T4K-d5eP*?{Qc5z?ED!%7q47vn%Yuz!4E0_z59^)^yA2s4(VR-a(j&@;m zMx(Y#SryaqEjDcBH)AQ1+e@zP=0DcD z{B79CEE=#bzfX>Hz!3vyV4$ev{vV(eH2OhHwcofnrt%L+J0^zoM(xtg)6RMc=)O(r zCCP=ESk(kz7hC8i!0?)=bI}xloe#l*2VgV-n2T!oT}Q+v##P)E{2*Be#m-4Wgg5zc zj6iL^{WJ8n&~`UEy`eN8lV%xcy!N+2UCY51)fE)rH$qq9pvkJDLX0N+i&4m z2XE!zcpcmfgXO!k?hBBugT{KyQhlPdpOE&;KM0YiM1iOS3Y=$UDCguP%Td=hYL7}b z3JY&Z)gYdG23b-(_b7KPRt4rYQ}0JpJa-dUvCU9bJl9oMu^}Y(8~s`JH?`Wr5IS4AY+6sJ6O`s_(v$@a6PTAT_;HN{2rbWb#`mM;G|En0I_P^2+V;D6 zt|`_AjDzRCs>UlEo&yV!p34>b0eP6h!+04ZeWvZXwU+0EQ(|B?LI+9T@|+GX zFPXgH+5y;7{?Lf}E0Kr-Y-jG24A6iI37i%DIMuHC9COOhhL63@2&!v6?pr0Hf zY+0wZ#^N#xr#cEIcd3jEAHxqQKl5F zNzn}y%veZVaQ6V5@r0v7$=Z>ufsnZ#6zDKdJwYGE%u{=Xhn=UCM;dv2cS78~L{y=> zHy~ud>I)*=;qHfEeY$%r;zC!C*)pRpWHMKn7#A?+i%WKI$U&p+Zq?v=4j!a~KR0Z5 zj|NzRM(t~DK}y?`w8@|?k-JNT?s8H#$uhOXc6W8SF6{2)ifD?ve@K8!>%rjS?k~}T zyALxx_>D;{Fmfd!+30>+jB^Who_gGJ_t)K=epHGfq!<8-FuKR!re-)Qlx#T3S_zr! zDJdg}?zf9Y_m9HEcDM4lgFKG^BJSQSs?gn+$^zx;5QXk%VSTzg8*!oTenw`LMJDek zlLtdgo~SM{)AIbtnCWFPX%}MhtT35GCbtU{e>kpRJgg?{fx&QanY9#-IqNh_-TH6pUm8sASKPtgMi^ zh5%ez$}BFnl*tnwcFZV`=gDKmF^QR{L>0!&NpM5>eOM*Z-M4kunCTw!!t*ktH^^k7 zGPyp)WRM141xB+Y&(yJ)R0uJ7L72QpCM|`DaWbMDjw-4=m7Ou8(^$g6za8Z?jE_R) zaCt0jLE|H6q%otk`J~+f+7iV~iSo=`sg@*W>caaHGw&gE9eL(uG$m%nRzh6lW1bQ- zL(oFZuM-17+(WPqQc)@?(*iPm4NP$s!K2hopeYhC z;4(O!Cy0miFm+T#u*9jabN-k&^X$c#q*Lj`GJo)oKDWR$+e7W}G8&nX1nnhI_O1s!a)dRxAj(+8lKpr!d$E~6YqklEH zfz?O?$>DvzAC}&)5pu$tGNX&gBwd-*4l!w}5ZaI0!^z|*29wDiukFdVgh?GTDJx8j zdu3=b+t7rH&XCb*H0I!Sg%UFDF<3)pC*Tt_9)w03GD_Qow9kUJBq39xggKHh)jE7E zE+u4mZW|7nKl#uCw7D8qYiTy@01_zExDzX#i0H--u|Jp?Syw_Mj2#sfiN+;(FmbBJSsudKF8^8)u0y#e_kNou7bhp z?eBrRpz$;`Qg175Z_>U6+LCy?L?zW^;#<8v0=YuGJs&X__IBzVG{xJ4%fh2`F-`Gy zPqg6eNhJ0gO))r7S`xjTAQp;khEnC<1D3aYcW}B>QRFdFd2|w0=_HRgYL1R8NQg175HffiGwj|yz z5w;(dbSlMAP21Z&SxJVLgXGR=inp^$!=no@P4V_^Xu;bJN$fYi!LBz@RnnV{?L4u~ zBUJfZs4UCD?H;EamEti{{BX#L?LW#mgF?xkB-ttZ(l|oMVNM`ghnY0lm##n}YaoFyJm<@YdHF%SQ z|2in%PR3xxc11uYXyij9^|sQ!P1;XETM}=V2-`2Sic)M>#u_NtzJ}R7T30N zV#o>kGNY|z;u9vuwDL}GM`8O$#BA8xs=;m!PSC;EV6b|-1|Wm?%0MIaw$gr1+V8$A znYT-X?GL1A5^R49n2Wb>VsZ|7JGl#*;_cj0@aPU`D&C%m7QB5KiT%c_7#wIN>CMLW z3bD;0s@x1Ji??T{I&Ua_#-kL;t>X{4vvD6dTFCfxeu9KqD+pr;)Kbhv`d&|!^O^+ zS_K!A$@~zLO~Pa_ne6_G=Pe7MNcg;Ei*%1*cOJTtEv*7 z3r#+BGaZBFsi6ZebI|tp?xzguBctjqZd5tG|)*K=x zkVS!AAW$B1_yp%mLE|AfjL*M30+aIj7o0iW80%&T9Q0F5e!cU6kH|KjiDSe@oH;Fr z4H*N`^Sqa0x9{b>Qa&pawinoR1)JuFb4MiMLDo(9(@>uB*y_b)VqmMo8P-HJz8@gR zso>}}Ig5Y`KvTf#BD}m^ zXWufAfLF4)GJhd+P2eIT=T@zdF|oYSMWKflEPn|PJ69=>7szAR=M?37TU22dIT!01 z0(#AHFm-prME~_2*|YqyLe~qsnA>h{-s_4w&>l5y_;L#UwGrWVHyTE?9hLW9O;D5VN3?K0Bt-%~8K zi;W<}i$sw902t0fz2;xen1UVWAqQI#G!elh5!8oK6^fwbu4qaGjr|=Fv<6yB1Pwt8 z8L|n9{YE?d2{e*~X0LX;#8jK8er>2PtKH-)>3Vy$Q;IF52=1m^?bWWbeFH%vNXb4U z*&ZQtwc@%X=l(bU!YcuJR0Pcs9(DvNj~(POOL>eCRTx1V!41y89usm#P)f2!P~DJ2 zFc1g(`^cobGHDQElB{7kH!2KIVlcySUvt~5Fa?-=PbL+FiSf+Oly61QI*lMJZC!Y> zNCfFjj&l4)TtojpGJXXjXb<3wJPf5Yf|T}W($2+oF^fa75rla8`y4ccDMU-`djMyN zpg1ljp$JMnhLk7~)a(=@C>yhu2&#h?B4|7JuYRK~YpL%gL)bY8=@O<2QvI)YS`n1m zj1ISRkW!RN0!2P3!Z~QGeF!fRq-5ntHe1MCCm~yN&_cRBW)A8icW~_pQXcW-ah>wG zR8(OEP5(_Is0x`na?o#Z1fBoQ6}Cf=eler-$i%Ho4mPEDGWkWr@Xe?kw9sNQC&UCO z1Cxu%Wc?0_fTJQmW)9lPNkrx#okiF6G0KqK{Jk8j3k1TtPRO-5Hi=olVrm!`Fj#Uv2sxS zG4ik@NO`m+kIKp;Aga*$oqv@G3P$Ci58((#(DR5AbqF?+aDHbp*@P7hDg5OSlXo=? znGc*{IM!m)C&UDmESPjBlLv%}al{!xkvZsbP9idbbSAwyzO#;hI}|}Tpb|p;bGfas z()J;3b^vcJjpbS) zb z$%obwL78YFf=;j`@f(Xk6sRp()vkkZA`DYKOZ6{;`Vv9o8d02`gOuVqQvAA=Znf*6 zc>CUgM39obM6yqW%+-v}mK?OG*g9yM@USCDdAvd%GnB^=QH2roF}NXuDn>cK`DGeG z7l#~z`>2@F+hlSLnBe(`OQA=kgAWVMhoq?s8rD~ZRCYZCwT7#M#&-~`4p!QaNc$`H zv&d=RBb{KgI`CW3XeuTbu~|LJG-+*CFFU5!iGkk{+2OM!WxAM5UjkD*?_iIIUpopc z18vk-KOnYuL+iAO<`@je+Iur680x|fL{vpg+Nu9CinQpg0<_U$QPyE^dKSCN$7p=5=w1U91q;1s z@emeLuR&9=aQF9!_jfUA!NM@KfQ3dR_8YfjaKMmUXJ^x&B`S7PWj9n7EZk9_;_Pgy z6rYo#5a&MOZ2G61wcC(UvVA05Eo82wpU8%XrhN){6>C>HzJMHUEGUot&UXHAL2FaYn5Mp>(2t}!@}3e1Zq<+SK`u}l-HoD7x4 z*N@ksINOOz(UcVDgCdOUq=ObCS>u$f1<8I~#}1cImJQ#47=3OV5qnNb><3>GFv;Q@!QBMY1{5i5_%Pv_8vI&=Ys zs;^tZgn0fB`lzp!wkv7>Tw5|C}bf`@~$vd-f-mV0LN$@NP@E!nk+qDXg z@nH}i%LiprBT1GCGQ`~sWHbvc!(j`t;4qldwxG|fcN3a&?_ePEc3?i{AQrri3xMC1 zLSnyh83qRukO1u?ecZUPzC)`*M^k8UHH8|xvEJYdCAfVMG*-c;8YD`0C+T*BuE;~2 zuvg7mob*Ba_#LcvaOvW){KP0ecahJ-BF~k;lz=*GI!C)!Vn{@tHQlPM_^|0}tnGSJ z;4vIPgzvtna+ze>hD`a&B|dM8_f81vcH+iGpgV^YIkI;JYEs}y`3jBkILwBV5c{jQ zPIxYW&$#S96*ZNKl)8FV43oeB^Y?R7_5+1ckC-jP7C1Zy4U!ykyBplB2WEc`27D(mnn~n` zP@XyzO+opbuMvmk;US69nP?$KuOYGDsEomZJ0w>D!;;bQ;09{^+0=RP#}>+0UP2Gq z@KuVZNZ|oRIHO1`>$l`q_u!@sOD~m~Dh>1&> zyhkQJVPgFFjWf)mZg1bX-x+2)jU^nMpo8DRU=5oZSeWqq3p7$~l{TNW->rxd;IU$+ zMEAEBO6?>uZ8MKmR5hJA&&*bY@CX8NFon8_xw-zba0fveWg8}`Z& zFUHwOotr{uSsDD*K^+PPrPxdgHz>j@LrweEfn;MP`;=sdmW#hTe@8Z484i5Gt5{!A zenxoMF{3=TlgCTSV}hu{Dqs(|fz?!opCe|{YiP_|5%R)0GNZ4^q`xvr4l(JVfj5Hs zIGB{RnEZIL?aB(mh5#Kj85Yx4&J+rrZB$y+>V(7ltw}0S!kp& zqqN6J`wnP}t`ldQXQoIECNZ-Hml88G;Qw&Uq~3?7#7v95h>PbjPl=iOXdz|>kQnzF zF*r~LDKK0)y2UuBsq-KCR?OT~4b-7LqZD!VLGd{#!g=P0FDyn9GfL(n*?U6fIuGE| z9pONUo>+P2Rvd7LcZABLJb8>#9-T!M#>^{%bJuf7^iFpha5MAFUl-Y4s3bG0LMDxr zNvRN%1Qu7OD~=h^5i_5_g=CT!Vv-LN z9)Q7`XFfoQ6*O*xMjA6pTaUC8L0h7jDN&yBNi8QabFCdS(*c=q%p~7~ro>FM-H3}j zU@VE5I%pwg`jQy$17^%@lVoA%ne)UrS5oJ7ORSiwcLAtFc}6K(km6NPg!9ZI`}Tmu zjFPn`*(4!z?b}B-%rmRyDpsDkQf}PZc}97pkVhNkah|Bcm`N0$x!y(Mbh`T+SfB3R zaG~vm^JPYz$mGOgad#((54$_6dWl2ihuy6jbmQPW9UPCr>h86u+VK7}Xr%5|+8(5x z0ooF|yF^dg^=Emgo6GwV-I5}{3E;EPvXc54n&NKH&i{wDF9DCD+O}pY2w+SQ3ZnuB zWmX2kC=jCw1nEcz5JV7AP!v%S5fVU|2~k7Qii)#WK~ZtSS)2(VqsXWT;*3Mbz{QD4 z(f-%kyH0g=r@1fO|GoQtSGrQG*4gK*z4zJYRCP5Zor1vs)I6{j_hp5u$|-*64({@gYyKzHW z81q`hei#;MLyCQx*d@SLO72QU_jH*+C7CyalZ)KHb0+lU&iWpQBKL?bkn}P1Q{*0i zBgnm);E??j3hZz-Ns}hJo5*a1W|y34lm$V9io-XZK2 zfm!uXDQR?{h$$s;bYCNPVvXF&@g6yDRE{2E3gzyPT!BO}H!hhsfXtNpNIjzh77dVl zHAz|tiT&VzitbKwU;P_5N2vvycyambBKHtntkHcKB?z92gheX1Vz&^x4A@G^U8(4v zCzX@Pz4t3u?p*%OlRF~=haz{uCP?}c`YCdc#1Z5^k>HU1GA<6+mkej3`!pGxuV`~! z*eq*=>rgU9byUPRM3lY85iobd{*)Vq#w!%|17Rx!X0dM2=R=H2XAmaVEut?=rY)fLl zeYuiyS1P(+Wd>8Zdt&57?k04BXmqFGP~^VPLOmw%A z!8w~Yw}s6jw^N7B866dI4iR;Mh(>oKxuIaZLSdPNeg6_+7V8F$?pdGkQ=-cJLE$iR zD@PVN7AVIgF@o&<; zE$GXOo9M->(F>LPOiU+uE)W)}+=}f->~BjdDR-r!d!-aTlFT18(R~vm#*;g1I1WYb zXVyW|?_jFP{Sb~IcQ=AV_7GegzECn8#FWasoea(}+I&827P%kAE<`lC6>%jIjev+o zcU!rqV7x+MBMIC8qR7pq9zrYmdCG)uGo`{>+(dbqSCiCL{Mc_ z16!$NUa9E*M2a4fn|V>9J3XdU%cy5cwZ-cp>F;P>;}b7@v!UBsfax{4*NQ>3lw_@d*I6ZCTx$`!{e}T5L*B&2I~^$ z+fee~W2BRB!j70*LpQS6av#BY7GAEmh9+`vFZMwowfIdkpG;=H6cgXH*buP?OL&^^ zi{K^4ABS5eyt`tR!ftuVF~2Ty!$!0g`*o3d7;2{NNpbyopRF!>7GqlB-jn_4T6XLx zMcU)MMIGA@b*D9C><32eM0h)Zs*Ijr$MYR=zCu95^44e)H+syYNO;t(C8i;KZ6soE zM-TlxACc$h#pH?kz6kD?@wp!Nr={W^?y1asFW-==Nzw!Jx}=Ah_~4rj#^F$AgOb%q z0iU2Vk{%}G2RxxA~&IY`_8{NuPj&I5FBslo>wl>vqX{@M<+D+6{ zZE1iQ%pCC=+C+nmn3;SzqM4<>cATeJru2I+NjfV@sz=fU&I*#R5k7vBuW>OQb`4BY z+0PS_10?zVY37Ix;D{!(^W}7er$51IP|il$K^Vc%=U`~Wo)5fIDYj}WU>7U4N>zjX z0QTU$=yBL;#7+SgL;WEgB$WK(^E8^n5kZHk<`&UpOXxvZ7et$HfsR7kV+EPfP zG0y16t>Izlzk8SUY+RZkSgZ|IBv|CJ340>PFE-{M#n5pGXUFxW4x4@XDUw#WOMAyE zcFM$j++6-V?u|zKpq|lyWFtT(FJb>U{1Y%b$a=mZ&v(c91PSI8G^P)I%mHd&} z1EE5p2<{@i`tuPM1M;UibA6_$0 zuCaD7t%i~pj+9 zmUVkrbm=O-HFB~9`3#n#UXW+qj6(_X(hm^Gbs>)g`KvfWkoPAzWbZ+83g3hTAoH(G z^e<$>jL_aW;kT+wdQTUn)32buq)lH$~6H=+kAcgMX&4@7vARuDC=s!@ z!6LO*u@4dZ(_;x7Jdw{-YGQbc@vc5I6=Nno^8(fnQJ=~97Y@Z|=Dr8N_zb3s&rHJ+ zd}cbqAv+rvhchJ^nu(#049?TExf5)biQ(=;6v{Y*A{G--4~Xc*aGKl?Fs`Mr7YY0M zU!wO#$V<95?E4NsCEEFUOgN0sD920Wcp4lm{@Nb)tD%5b2q@M@E*D$rRPUlWIMw&) zvELug{7apxfhSX6>GHcI$ySmykEDfq=1--uBtPL|dgdlrqgr1qBp;IGuSYpCd;*SW z8PZ=)f6UWg;56)-yTYvDUWK8^i@+j*|0fQ+nb_IDBC1|s z5aGR(H%RZ_#7M`i_olkF9v=mK8wpS6g4?oGW z#X8N}e1H=Je${Rp6rwx0i<=eyy2f)dtVxRep@U+333V zkOY(@-6LrSb3yWT9LYXhOp?!FlFELWkklhdb&y2tFTfG4N`}bklX?342PN+3W7gL7 z-a9ZfVlM(-sTA9Y*tZm$`a9*|+HfQ6!M;cwwlT4DfyGdtC;BGuA1;R9kE|CH_r-4A z$GBhqE`~;GK;AxyCMh+b2}#ct(rApk>%E)Mf48#A#ia>?#ronm#=QF)+S{3YV`KgW z3>}AXeq3Lgv)R%INLryXdytjR(bjwKzUl9SdPaMajR%>#-a8144zivP@>ho8hIUou-^L+W5}_5A+8_e*yN6T6DAM4{Y&hT+1QDj z+_%2!?|}Nq6tc|$o12x6f6a`vo}b3^*Gp>^vdW4jrf?sHxRLeVi4Z}B(#vP?@-q?{ zo2YiL)Ozp8G6rGR;AAq3|`x~^W_9*sEV*i*Y*kC!8U|iRcT=04vb}6xIfyDq+;lvzDzW6dR{8fZ* zOk6K#*t>E4H)W7H{G(@aZEQwTE8ZgW7&1p|_a*4GNjmP_I2qShoO7)Pu-mKMmtlU1 zo5#P$7*UH2as64wRuA2UzE?;bb~+}AXn4o1vwvSwp&#lZ>&W;t7~R^v%}Zvq_54RX ze;dvxC`arU5j3&2`(#9&)b4H2LsdsAm=LVgpD5b{X`hwL)&gy$j~NkGf5%iSct`8h40eWx4p--U@Vv8;$M zh`0)f=)6Aud6!6PcZGdRSf;?NM`SkVy#C7bv_H|jzE3#JysjL($#F2GAwR7Qjl?>q zqJAK13s7+TXT@N~eXUo;^Y5T@`zH5EP>Q}b{AZ)sSn2mZlFU_-t38r&EQTCwcU;_e za!F3{NNyIALnP@561@Ka)<&nu@p8Iq8=P*1)1ce|^RyoS2ZMusVYI0pq}b}j9+@lH zOMapptldwL9PwTpwg$1AfyDr{qJxBzOBRaZ&!Lr=xL?OK=*GPTf7ZC)#@iL%_aoH+ zi=>le;Ooo%{XUM()zYppe4N11tp|Nr=ITJpnjp_L`o__%66C{{gXiRJO`+Q|d#J&I>^K+a` zj{e|?H#kx4Ua4ulIofk$d>m#6iSay6nqG`&b;Y5?_~FHf<6I1v#CSQ55aY65#qS8< z;_zZgc8FkEpHCD&Y)O+B%yDD5(wk4!31SUbW73d~yiBCY27 zoOv?wv|e{HIZTWzM+b7$2M5>Z5C7m7Q2`wZ_^pIjTI6TjrFhV&!pT_lax?wingw{~B|ODask zRu)Y4YWFawmjtzY5@E5oFtVyO)*v z0i&a)=da=UB{&}+q!{OaFmAf({sOYS)b2yjGymn+^75PH@=E;JXr(6dY$=0ef!+gN zC_&zcfAfMoBN>MhV>Nsu?h5rTXlC$^BCgp0!~k$$2R`E+r_0^0oUZEldC z^equ4dKEE&h=+iPPUO#-4SaD9g-s@GoWQKDNQ$~ZAI`u_IFYwlL`D^|g!TcDpN5dkOTe0^LI|JAXzWHA-)h zg~FaDtVm$iZVZ&>^pXYqlxV4TE^qOAax2GTa$Eoo=JeIDC8~x3o+F@%Hge!A63`zm z;q>KL$!yh^j#oh*`ooLg7@1~EmtQBz&LUoIz2cE9drn9?(^GvUGhC8U9!ar~yibz( zAc@#FilJtycDtNj&C`WA4ZEJg80hkA8^|Me2Jq@Oid{==o?;h%NhO%ZhoR!dd$i-Q z>xgZvw%^EUB9#2}{bKkqaL1(ahKO*J#``_3pVPzXypa-H4XYLF$-HtF&PJDN)zSI5 zrP^k>K@q=^VOY0z>-jHveizPH2vQ9C=l^1a`){*s#vsd5Z901B=lPmE_X^Md z?o#av%Bs6FPhxVE3_pvNMl{2Z$Dw5Sj*la(r(*ad=S3d6HIhsrDw*a>5Ls zEB9(mhF6aL4ieP@sE8c_CYl!JN{_0Zfz!3rkW(=^xWjk$OYZQU z&N}vQY+?M$b zA&Q9`jjzowUKefLV&jd`_}kTSHe%nhQ?b~ECl>8Sv9*Z(b($Dj^>fO-g~3c(rWl5~ zRfg;HN^6GMLj>F)u3#oB0YGup#^(7H=ut$>r0 z6zSU`+BR3D+3=U3vx=o3u@U=JSg7%(!`zVcoj@O-8Q@}*cd!ej>4L;Y4t6SH?}Fie zjx=)Yn<^vlHB(?Hx$`}2*Sh$jxNI3l`Zw9K85Y4>^!~>C3$7F~oj-}p_klV31ny=G zUY@fN-@B2BG6O9yuYVXk3G$8A5gqYfUjHSVjZK@?K*hBAb6m&L*?dDbU!lCV&p{SA z>dWivx#^$d<#tFTtPL4IoWh|(+T0ip0H{N$=g;K%MK~XKR~Z_tLY~G0$WL?TEYSst z(HaUz>>lW(pQ;_HE(2A(@zE!eY2JVFMDpo0K~rZKa!cymN8P>Dne`10CH7Nbb+{Xb zP{Ob(=bDhULY%~Y9{+@&p25K|)zUmkG?_I0vB~tlP57SXr$m^XsE8~grT`JGmO^mw zXogi-H^K%8%z8t{k1OC^;sJ@OrP>dX!=z5-$R$TT#B!GR~xZ?ONh(J$T z@RR#;!r z2h@pP!yt+i-NWqQIZ;Lt4#kPqKLSVj8>Wa8y@w+>(KQ5z>eUw&n{{06tO5*wVL*Xz^q#TpT zv0;+xFQ(9ms&Q7r@3}qLIVLa4{j(>_yR0^}yWX0Z3>?af1 z?_+eLO6|oxw1^_eGJQKfiWBuo6MDODyoTxXVB1ZpD)QK8;iU5Efy-AX8N^-JC(n>w? z@cdYkGF(hg+_Kfk3cW$Hj3j>-veWj9GSwR=id#P<-3Lsp6KP-8lHpxtxIq|7k%`tJ znDPEQn59mn*!9HTCD>zhqDp0=OPIseiSm#W#fg&K>hd@#)iMqvLy8k+BZ$J|F?!-e z9dQIF+Qo%f$UY7ihd+}%VKNay6QlJR?cY@3I#JtA95&+}ir7iSi$Fv((Fb?)$oQJV zz9Q^4fmuIt(vVDaCPhoQ66h+obd3`!$2a8YrW_}WDRiPq4~i4rji~iIQ5lpF{Wlv$ z&`0#>XOjFqo)%i4Zsb2C*{z;fa91qJB9~;YM}nXO$?qh2OGxZd2!!Y&G%gdZWH(}+ zNc(bx3=@>0g)o%DiDtvbhiEg=zN58J0<#uUZ^=a0qE1PiiS`SJaU$htK#sp}Cb{*gm_q$K=@!Xx z2xq?&ErJqsBEG&{6+s`-qb4MIOG)N=B#)^l{sb;R$uO6MuP;{;)DIwONs{qGVn4}| zJlamiG~OPMbt3Ic2Qr+c3|9(6DV*p6RErV&SD2-(DYhfAmSB(3i7J(e)=Nzx(;4R{ zaiVirad=LY(GrK^M33DGM=66T;zaXs1ShIZaLDe;sV-jc;}WFm!KNZ65^!~urNB*vPk8mvg1iCz{C<3!34Ajeza;GV<< zA61Y?Q5O+)kG6EZ7))1NE75LU8JB9he5|h4bc4|iMI!or2}$ymq`61p`s>^{SNj7O z(_g=UNh<#HLUK7tl0bsrham@?2|fjnGed(d5wtauuy4o6&>ZHZtW(PYq#+TsnClQ% zP`r|M0uDvcFJVSF4I?jtZelEjtU&~a?6+}ocnXpiwq)E_(Q0F(*jRx!HaFT>J@|p_ zlB6*$p)q%tq&5z@OY$J>miOR3h+Tm2ljxH)ItNE+bT?W*1ltb)zzF3K^L96Lu#&)12J$#pW=q_rElHf9fbE8^Ac ziX4v=q`M+ta8uD8`j}2nBlC1&)+~h01Q|DcPjjhww+=9WHsN-;PZG0riji)LK42R_ zr|k_)dhWeJ?z2#8?8W-C@3$BqhQzwKJ{HrG{Wm1qt~gM_P9DfDDUhG{&(Fm9cx|}EpzToR7BmiRk;f-;I`MX{*l*QH zx$Y%bMglH(ZA-e?wQZ$}fof>f4f}m4(Ff`}nNM2msZxI-E(1{C%TVP^}> znjfOo+#u;HpAs!g!op$lxNir&9rAn915kjTG<~&E;#KL< zYb1GINbGl+hK@Fmzj+55ij4|2<2^E5rwq3ULn-w~9*x+oSDDrn`vI|8g4Iy*@1P!4 z`%2B>H94DT${)cj+ybLAhyLJcpD`JSqW$N$LEq*WeaXHXa0KlyCpcucz{TMbNt|X5 ze?vydw$=a+84n|Gz#C89(_fUmz3mokK{g+8} z_mli2m%1e9dn8MRSm2R&EA!MHy}wsNzy%%cIvAKO*qCk&uum z4vUfx1k-|;udik?WZfm<#4iY}nn6c;92Y5{Vp|dW8nE65nPXL7#zWqnUJm0T_6>2@ zwB|L_#9oVD``Ioa+ZR_==mzE%bMq#)uBg;+ggnRPj?OK$ z?sHQ^O|G`R)R1uyf=gR9s%XQi4ic5h53A{-g>nS!fJ3Pfw3j6fa(WcMw8X~ypc>jP<6)W{Oumy6HIVL*{ zX7X^e!~L9RC6un_7G`W-Q)?!YxfYq-XIF3+wkJj+z{hvZO622k1K9$tI4!~zo`vl} z*5wrF5>8j{^2x7I0S1+WJ2b9i)7bnS!zxB7xcc7uAMVB$O{>r$b(}lMcn%odyRq*8 zsKc-4=kR<(oUeE{_Ul`yTyh!`vV;~^ z1yV2E&BW^^g{)aPl%#MS0x-dU4o?XnHD4 zm!vS}Ee@B7c11iw#J?}+2~#gbZsn259SU1O*cyRZEs;pIUMQ6GkZ7?nS#G+Tq@Wy6 zkfR73ObT`0MkB^ky^RM2E+TNSHr7#Wrq9hovxuSV=yYNS2ah^H3&*XK9F=#oUQ^qhLyjc>x&kN#6apm~t#`WzZS}+zCRA|CJ2})JmgkaU6n-JI0OJjSb-t#Fr8?jfq z39$e`)j-dG#`8x8R}5#9sG-E8P*0Lw@^2XN=q3dF?dRG_u9p*V{r@dQr&4Au7A``F zNnW^;3E#^L8U1i5dEw$oi2X;=UC9gGafG~Zwv?83GA<5RktAt~g{|VVKho|)m$`Z2 z($_gyCg2qjCSp4f(PH7J2|P0CLt%Rfdr4qc%2Zm-&E&R{ArdV_N676FlNXd@A31JN zj_zU#BlTi>m18|o08(GLpMX%NC-L>=s>C+w(P5Ib5E6TdTxxD>#;qaGnuK1&`i+`V ztsNM?AH+V|qlKXqv&3&0LgWRQrL8Hp2C;7mw&G-YRP8IZhMXxmRpx{@F^r=9D#o>^ zeb$>e6zvC0fW8aRY0EY)7I?TLL)u*aZ%r8c07Ik#!te}@#HanC&NX`j&#hob#u2#oL|bXv6Ug(Jp2 z!6Ex8TpUi46lmi9a~Y}gXnPgdF7?0_FZ)GR#Q8*gHGn6~tKj#^4M!9A3hPeTQh`|~ zisFp>_X}x%qPV|7?%o>hm7@na#w$lJF@@ScE5mOMj??~RXin{`d1~yE9`zwfJ0+>< zku+d=9RA^UsGf8jNf-%RrOT1ILtZC}>kb)d#eIAq2%6fus7e*qCq9!tjZ z2t=~cqOggCO%Ry1omxxsXoTr2@di{IxpQkANI7mHM@QwTBc{-SMnQCFf90*9@@c;l zDp337FBvtykscM1WN$xOXsvpY|Bz&xdf^us6+g**mt=}Z@~x1}CCOqTu?I=}X7-88 zK(DbIu^CAFavvE+DnmnID1`$ROs502K;P7X6#D?NT?Km#4pgZOR2>bv8E6!$QE{Np z5KK`A%2=T6SGjMVEHc65u1AQ+ewTQM)yV!N0FP`^% zh9aIOVki*N40Pid9vMGV*z<&C2+X<<5vP?$`DlJhl!3~G!#I#~yhx5;`;y#RC#F#Q z&(why(-(aX^xzV8pc!xyRpSTg(NdDUASCu^G=J3Ov6Od%VzpN@O384&GPDtfQfNO3 zMZT=2^d}ir7NLa3G?|+X?F;FzX?P zs3eciWcEo^dF&MqqrGzMAjkgRB)2{mQ>gtea3FbX7#pkoqfmj#V>X;bwJ(z%eMgd) zg~T2tmmVeV-@OqH#cHo+l#^kMGBgy1QfNN~v3rT_CfH-pzEW{tSL!#> zeg-~@_NOucJnb`5aVXmF8wGvaVDv@%Z*c_ee?!nf`|h|ne5a%)6Zd;$r2eGsx8=Lq zfB%eMR7D&i;%XqGabGBRH%;6ttZI9}vIJ)Ri!#ZIV;izh;<*1+IE?nnQJoxzgQEQw zF@@THJzli$5SR1$I(KS+2b@H;-zz;zCdunUVqe1KceJ8m8E@poYOiKAB*QpmI6)Yw z{R~7A*5QjyYl=-H_CmoPgZ7n*`xJ()R-JR9qG&-G*|h4!;Cgn0h(Y15iwyAyknV2?rj zO2vJBhOKJ9!)SkdY}`*WasSh`(6=K-U$ozeBWORE;E??YwZC6dlZpF3WTg7i_B-=j z?e{#%aW|qWq8|~Xfr!TaRJng?Tts053F{#+>nX}4aeoG~PvW>gEF4CA<+zL-Rl&g> z$U7EQkVa8Mh}spPLDp+xFg>Im=QzhY4O;mD2(%d6CAS7c*axq9y2e{VWQ3ZBsA$>?N6NzaH42=5{HtIczzu=U3?=>1$ zqZE4!u~o$=_Zdih&+7?xl=mc3#`2oCVlM&kz{u>H8bp$x_2SH*2Vt}ei7 zcl)s#gHpC1H}kFoLSSCJ<&()gUYOOb%^k}n7zT6eF2I+ZZ46HaN&MYC$kPDEn>&`J zk_HmqvHTK)N0C;=^=%d{`1Qg>+mBnXsc^?~4IE9owD+0{T~gPXOTq;pjP51M9m_@| zjSz~vlekI1#rMf{Tkcr)h7EEzHhDCrCf=)f5Mvmz8=}`LtFp}_TbqjAIO-kC^8?P8 zyoY&V61s#h9tKNfNxq6`9g@OIN`hi6&}3S;n$v7_S{Q&snHIhnj_^Mb zQc7yrh$Ezia|sUF0bCrOEZGZzFB?%u#B={ev&Z*vQ^S_WIcg^674bL`7XuNU7OuLA zM<#!M0&V){kE@{+9WS`hDE7B>{Z*1oQWAZ=HA$|J znZ&x5hWkiPbxCS@B>xD>yCmrZk_f)Ppa#=F-0V=L8lN`%keC#0s3qn&H`i~#M|sHf zbczf?-G@vY;4tQ^xOI{4!slaXMcBV#8HD{ei9+`6_$T}Xvk8Xk4zwJ7$W$9&&BpKP zE<^PkQ-@A8!;mJ#o0i~%@g{uf_;DP{ldap?=sFlJjjrYF7_w#(9I{WtKVeOGbKOSG zmyfm4wQRI88pY$PdCt0Uz2P+Mo0w5qPt4(NG|bI|abFTePQhQy!w-dZ@|+$?_(rh% z9bJyHyye0kI*h&gSRO>3@tDzA4cW*>=A)4c&$q%+c0J0*nROpR_wc}L#LkYpelxGX zM2xid0EEPwQCqz1F|-PIm!al!9}E$1^Ev7SgfPARinyNaV54);XoZmg-(lE`@`+K3 zheGgAD>rDJl{mxihFX_zDv?6`jFh1wIk9g zrzHF?40`9M_>mO5vJ;rgoqgwr|KjP77i40VTzVE#xp@B$=5#NYW~{@ZtzByByCOs+WaUiK?uNsi!RdLG}Wty0z$k`$7p3WXsG~`b z(!-5$hddf7+KDt?`sw)`2>X3ps;{-#Ep^p>ut%Fw?8(GF3v2}kPvkL`ntgATYDPTf zYectrOigA1&ttLJf<&>;4wRK79R5iE)M@KSp@zdvu|w~nwGSA zf0pYp{SnL2*;f&*iP#22boTvzFprF5DXbk~F9^&!?n*Q&i?XdK4inG5!{xq&@fhXk zK#o!1U}3%wwnWuXKt}?4Y9ptLt#qlWXb#?RfLYk*QvZfL^oH#Z8JX%xm(L?fH6{7{ z0rrF>VfD+}gJMaZbxH2_Na_kn50bop9uvp?G^9eAkSws?gxwDq;%Et_(7EqkYS|8d zTfrqvbmDythcVyoxCi4GUIkl4)7dzJrXgMwvU^k0*2oZS95!GK%sVi&@xE;QByIex zXycb63yCAKZZnRAiT6Sr%EWs)h9cb8G}?y)6S7(n9I{Ws#o^bHKZ545S?{eM+GsyE zx+v3|cpn_32C^~;cu#mJ_7Y+z0c##L@IS;YQ|}t>8Lq`s{Ql|JP7=LVVO5~t|A3Gh zi%LC+)Qv$MKaastuDOr%7&LDN4nA{%Ie_Lx?3MS&vJ586XI*KaRf`!blsw21XIlq9 ziJ5#iV#h0Jk^EM}CN}1LWFEcnN5CEo3M1f?xNcp=#;c(5_`$)Lq$7%sx{vXfUrgWcjA17)M#oiyiEwLKY`9jw~}XIxUv6*o~o?MGnPCT zf+yZ`_ij67jGLIpVxEe- za?xz8u-Sz55SaB8iUOUOpT|<`DElA6VbZK}+(wS7%CS>SVFLU~hTa-Wck*S?#ZZ7g zG;h99;soi@Jd(V3E-kdro`<`of`zJO8)QpG7aH}%>EM8ZNqU;WAir_i&drfPK zeT3NFf=yhiA65TK?S0ngPK@fGjYKK>zr?94I?XP?q3D0`V(O346aC9@1pQ|b9I~t9 z;_&^F(4ekNv$l-ZV%mS_IY$3^eqj~y91){|h)%OpnLIo#t;V2r34W&o#lH|P% zT4>GpNS=`D%K9Du_(?{%B)vS66NThMl1vm5yA~tKbE3En)LFcb6zfFVmygMip$w}A zkf9V#)E#m}?ENrHO;+qCVrvWb7@eq6o2VP5>XBNl7bXL7qIb9q^PDK-c^rxpJ<$)2 zvKOX^6V1mFoG3(a$UdGMtQSizHA&=T8Lcm9f8N=y6FqaM-#ZlX6%j3gh$fNFa&OdB z_X^uhSQUX;!v~^KsqUM=0TL&X*M-A4k#hV%j`upL{$dK9=r^#ziJl~>&xuCdtxnWy zo>Al!>CrxtOjMFS9?9kEiN`a&`AC|$BsD#fMnZCkBprps9?YuObE3G%HnRFva3bwX z)w96xOGoy_P7{VwIMF}IN%;Lgn59mn*y_Z7DA;3kqDp0=5*D$ViOzvPi4(PDO7@&6 zs|gOpiEhk?qbx?p#fgUD2u@Um;E;WoTXDxp!ZexaR2i*Q+Ft|q%M$Ubx$Ly@4n>?m z#CP~lG!y;an@1p$3Pxck685gZtWywqnu%)n=BGrN=%zm8FixZ#Cy`^Ka`X{X=tM6{ z99wtx2bEv{yVQwldWxh=k4`5^Mh5+&;M>YlPl|V z$wV^|MB+q~SR!~%lyMyn#fe(=f}@OpJ>o!6F@(?`W~u&)y^7fBg8jcpBGk=IA~`0B%%D$r`e)sYL)AZz`eXD|e;h&o z{siOq=y7p)jpRD0E9Fcp8LgXW|FX75e^lL3VHI&R5&r@rnnaeE&3{QE3Y$O}zwd%7 zVtZd&%{}|qkD5f<$X#Efzj90>M@QwTBc@RQQ7p_Ht7;#R`t^qrqJN1|q_y;D7D@J= zDTb`No&S(z8ypcNb7_x{WWGx>#Up7WBo0Xy3yJ;9e@Y^+u^X{Yq7n^*Q!}|WYkW;%UlF#a6|c8~oHQg8&B1(_xSY}3yT*x>;~R4D*H)>&m_jGIQ=Moc zl<+%IpWD=l&h-@OBt80>B>e4TTw0gYu{RUNRU%`00u!4=)QsQB&{P@Li3gQpCTfqW z3i`t=)nBpuiQV6ltsSHOl}aM-u>8^_vIZX|iL{8(KjTCks{TEwKg?GBaRmJjtNwFv zaX3qIok=3+$Y@o=>{ONk`&Iv$?1&Lo5v+B~>PrvJqwLM(PN;Dch1Di(PYYge1toPb ziCop4_9sdr3xvbyuN-yBu~<1~h$*7K7f_@ z-3T*oqOh|G+tZ9EtRPdh#Q*vW_$kqHW`S@R{gvY!ax7Mk8Dfg)FF|azkI(U*o zGNnh^BpD$jb}ux4^!V=%V`JlA&B!A|Q)Q?v45ic`BMJRsmg=wAUc~M{o!$OFiGQi- zME?_!1~vXUMSJ-_<3t>){yEeiW~=@TxuRBj*tHw7#pjFt;F^zxZKhgg&&Z(aMS$E-3^@pp5cfxGdpN@<7y%UW1$Hn0+Nogkj zyUA!3(f$nBuli5+3#*7?BI-*Iz4({=xhDP8gJ&_2)`tJ!YY!#J_MD{gq=b zITkC&3^7IYXC>oU`$+0rMD&^F>hCGiU3zpsNk#~X-HVgpQRn{)D(J6fJWhtD%1~Pv zN*Vu%B1 zWN4}kIl>_NBa)y$%u@XoyMfsKjsFY%D;NKgKSlqRNCguAAH>H0OJ4kAtiwBDw(5@~ z=zq7y|IcvVaMo$Ax-$P?B%`&H_GiF;)qf%pMp#AcBBH+Z(2IY$qiftmVc!t8rxCBW zf|N?)zw6QCUpS2Z%JCgJ7AwaLF-7!eCF58vVD7hOZ8XmL1Oox!fqd9{;yp8OC=@xuYrW3|G()I(fI!w zhZ_G~s6WhB{c!~SmlGVa=ZOB2(oFpKmeHz#?eDS-*suB*vLi-VMbspszVy(Gf4TQ* z+(cn@3EOkB>VH111fC3{|7`Kc*q*53^K%#hym&{*(R-{VNy$Qb~#aHzATm z|2Jdf{~0g-&!zq_TlL2g^e@r)?}&fGS(4JAuEc*o8LjrTKLhrw{^QvZBdj9MBBH+Z z(2IY$_i5ZjVdoIGCr$M~kNR`|KUp$C!unr0jQ+~enH-CiV}_U_`b!CJEyaWuqyGd~ ze@~JA(xYx986hP0BXX&!|KivG=T^{P&FDpjrpj=cFqCrsM=FEp%?$=mWJ#^E9^?b_B2%eF==Z2UnQRs#=meF{gq<`ITkC&3^7IY zXC>oU(@Euz{{mP4@kWt>(xV$mGD1k~-AsaB{TDy~XH?K%&6q%jrpmBT7({CsA(j8KwH zk0ejx*cwNBd?a;TlHbM{S%(YB29h)p68nC5bJU6Al1S^bDman$j7|$6j)bP>xJ7g--Mk*yxXE#_12; zc_-?((MFN0rAG%z(nLuPTu(zuQiC;>V_i!e3#kYr~vueM(CNS3K5E{-Fa;gXE zvq>^vNbJ!uP864k9%naVok;tVMTUOL&_)PE?AVC{A=Pvys=PPD8I9HkB<5GQ&CM{uG#1c&S*TpS)F2@@_N<;;yT zT0z=B@;KLtJ{-xhH{PL$-bCaA5zRycjzkg~Wc3k#w|jhCi?zr@xvp ziVXdf;Z|WNrT!Q~=zpzgO|jP#+d{C%sDGuBNI4RyTh6?U!bfeg` zLjlzvN6`Odf+F`omFF|8dfzIV71c zBysx3$A7B|`l}iDlA)h6`1D6r1^urvtts|CVp|CI81=7Q{9{q->Ys{vK;xhLI==YF zq3Yj)`a=QLA4iOTf&&;@BHu6|snjTp)b$FE=-h zn<(sA!Ws+AntBGUW+ieuYtV$1$QI!+`YXrtjTj zKS6r*21({C$!L${R$L8xCZ7g-d`TqJB{|(AnJ6S5kfe{0*u&t>M@=Gwd5b7^64Ac! zDaNv7WoRr6rAQ*DU=qXc(84S=S+VPg{kA6ieT+_2sU-3=g5Pzb-w{jVM8DCoJSWQ7 zjYDywTbsdAR>5p>qR}{l6RjdRWWR}v!>uLPnIv+njMjGA-xT)CnrQlPcEosxB6biF zv3SB%BB^qR)cBghz9ejiz^u;9_p&CsqB%b$N+NTG!#I(0d`*t|;NW-qPPx)2kN0IT z1%6B54cb_Dv6TQ35P^FtJT`wm|3nlqy82d+(nmh5m^CAL0o5|G-%& zWN$c$Ew^ev&k9SB0VZ&T`lqvA@K?_>HVa+^^M1psypY_>HsQ z;A^hWzGQ5_lYShveL40+R?_2H;Uf3}4RU*B8xq^88<2@z%==sxlek;z$Kcvs;L0rSJFGAx%`MIjKoLs!0s~U%X`nj5s>$U`3?)TS77yJFi z|G6%S*bUH%o8pslK4_0N%9|tYy$_9p4&GOj+zCcS>>q~En3NKv54;oPEWiRz+qZ7P zU>5H!sFzoCW0k6YPYo3BDo70!oq<0FobGrd%tw6jMezatv7P+Uyf}tm-(@@niq{n+ z2Z~x(_5GIpT={Bk#WVO3yn++*iq33SwXklUliLh0*4QBY5%RYee)FA8^Y!40EPJDXtSh&fucR>0p~E<_(BrfXKX&`%-{&- zBc)k6knXmU+&Wi2VZk^8i%7%OLV98DER3YrC+{%Bz(TG(3nPI-p_94I~SjE#ZihpXq6)Yw!uN36pi;kCZM z2b}u6;wF42IGA~$ATQul4>(CMA!YX6xFXJs<~}oSHfAgZ&X_S=OvwDIaA^P$G$|-n zI9u?=?T9@|2dwyZ;zL20=WGauaxqe&OPaNc*nJ1efEK^?PbAW*loAdPIHQ}5g^nG> zb>KKFq4&#IbDWc(1zix@+#wx<_G!5OtqA^CPSnppmG1yv@EZ$pK7j-hY%O1pW#QqsW6Uk0@0vKTH zQygR_O|ubo_n=+;-T@keBiHCuT0UBQ72jq5D1x6DNq!DcWGbiL%s8f<|^PrQH7NBUqg18P=wfJ2q*dKI~|3=A@?_8V~ zEU6zTsfD%+>dR~=jTE2}3AudK=o}9Yg#%&G?%B3 z4}>Np1tL`gPVYm3lH*ncBBg=MRa1WKw3Uk3yV22{$c5>gJlsT&xWbu!9daVQ@#hLd z>P%@CV83&&K(2|if1sOSh6kKmQuCZ&g3irpLFdnaa~YV*P-mkXaGG58n#XaJ3%5yw z+YGsiZj*6|xJ|82rDglz97WR`R4E)4CzwoV4(>Qb=R~=Vg`_o)QT4Ps0U-&IPpm@{zv$HK2oxYmZjE4vD>2 zY9Q1-t-NL)OXYQel1rNP#hVy{sD%PO@XJ*}IF)8 z@FjKHlRAJ7(n?aS^K&56Iu#Uf-og`e-r{`5^b!bPg`PsDR+xJL2@-<2Cz~GDH>Eg@ z`PaEP)wwA3!1AP&*)QR`PP^m_<3VR!lJnPr<>`er0?xFwh|Sl;dy!s_ID=&MAlc&K zlx$W%N>+GnfIlF#DJOzJ-@*O^=j;D1ZvW3?|8a`_pCmE<1dcSucQMB6;?TtSiSP!* z_;9o%6Y#!^8I&04vWH-f#ua?7~sh|C46X|mG$x{lbQF@(}nSm&Q$+*-2sdjX;H0E0kbzG2>gdcLvv@S)55%idOk$DRnQ|xqhBc1No zDmQdtwXkypzWzE41biakg#lMa-*9Azj%)=^A_GGy$EW4Ig>`_qM|#fewdg@XEg6*Z zYf)~Dcw0`wJ+kq8RDDg~3%ch;YNFdg+^vw;GWNir;N6O&(gTs|;r9=l5%?vhD2gu` zG2j?={ASBgDroNqau?vF&&dj+|BiO+WYmbc%(l28 zh4_|L@iTB`Y_`$GMg?Iq-b03VY44zzO4uYwcBe1qrbOlHYILqM=I?0N ze=8Ub5?-!XJQUa7_XHm^XdQE+**&2u7bAgvCzE!j(v>?6Y8k)p^G3POWvEz%0 z0_6=Z-x^5CwQrQ`ss&0e4se~3npf0H7JS(#_|{_WB|5e8Ijv_OdN1}h3OISN51p<` z*C^@UnU>Y`n;=!u5GCP66?B%P`GT{Vi#!)gWd)ztIS{FqSJD?8@ykZn5{&XI9OaN* zO;)&Qx2%_2$D&QYsTyBSPPPn8PPQ2EKeP`l+t2<_?VqLXKgZP|`+eR2(Ee}?2*%o~ z3LH%F4W?i34(@nD;z1Opq&pVYaRVtUI(H!5fQj~}uqg(mhZvQ7CmCql#~1m>CT76X z3mFx;xS$+wo6PH=Jx8NQ8F_6G-q=^iv#*Y)W3@&b>U*c+Q*8G(U@}6&wk%@kay?LQ z`Z30zc1G@Az_|#oV@0p)$}-0FAtxK*T{Mqp>CrjqIO39nNB)fklT+N0aqac|t?(?A z#8dNlUA2HyLcY9`c|v=%E(bF0ATB7t`1m}vM&bML!ZWC5$Ua+EF$Lpw@H?8#nx2w#f8+>}RKQGEj_J<>a{>Z@m zhyF~#1#$gJm;MZ)LLpgiiRau4;D73mG*qEKZ7cT2lS=0S>(8Ev`%`cMhWksLEI21- zxYOa-PV##c4*RuO0E&5k02nn7l9pHF0;XiK4g>%BA3Rz8!_!Bu(Egyr{S>|ThhIsN zoTtZ$44#ig>o<22-^tg=?^5x(d1TD3Tn$r_)1~;D0~tZPAGAyd?3=i zEB@@sFY8^Tr_pAWjw~*#^t|CL+F|DLdCq1mg1B9U`&KYXJ>d9&^Qrsi6ZFp_zwgg~ z(S;q=-uLJ4_0J-_@6R9WpG9@wpWoC!i{!pPKdyfky?uYaL;oydqx?|=3kw5|r*ibK z!|+$5ZS=2sA{5t@s1H=THk}T189!;->1O{y#EV{$993>N6{2D&wQ;#D%trh67C7oG z9BM&@4=D~eF_y&3u|=RT7E5B zc>utm(*yP;zkqJ#JKAQtv{`-;Zswt)=bCeSc^2ugUx3!1Rl0)HF{_fi!bY{|V;P%Zd*`7LlUX8-(L8lw+-1v^JowI0z?o4Ge zPowx<@Ak62*=91;Hf-C-0Snm^rN2G1Wn{amjd;)U$3Yg}o6*rQ=Nn#+b$KD=FblEr z6W|9Zvw>V4t}XF=8+z{2MG}!E-CG4p zh9JvyAI@Z0U6u<$EJRBtqZUG)$f7$^Gf*-<8y^Gs|0pCqlxbL+!wZ0~8Yt;C2sx~z z`y>=kGtdA)V@*}%mQy7~3*>}Mb@*Kgk<7i55OoE_W^}iY`+Z1#vOkGc1^nk{>^tQ- z*+?O!DYGxDhK7nJrBz9p&94@r4tyh6VmIJeQ4Q`w1Z(cqq_m zMc|ATfuciIr=P(-*iMf$49`I<#12PLMedN;an{8At$aG}Fw_7dY2w-No`voHi8!<8 zT)hqQRbLVL#<{!^SOUv;Hwo0;QQkl15X|K{0dCT7lWy{S5w&KR1Wo z!rLPWX4a7{!sPln3}}?P%p$#U5tE^t2eI$KVS)%U^jEA5IunwDnHj^tQi$={H3@P+@!=iK}Hp+@iC)t7OJ7f*MEhlm*E$`eU|l0afdsYDU{4k-cAXoe_ilbTRYDtsd^h24Y-7HNriV3U z-$_U(KSM;wUVse+Z|LevyBH}gsjpZ$a^Bo6Rjcs-x4QqD;~RX(W{SXE058r))lph- z96luR10v{~vJ?L1CjEbk@9R^sX~zn!kPdDd=QeYcVU8$y~_dC1p0!AlNu0_P8V_FIh0A-m16)hNnY>Ph0z9HVzD?pel$Je;&$4-n?P2VW6ce0a z=akzn?E}uGFkmBgQp-YoukD=}rnZBjA-W2ZsifSXYje{f6x!*5qdukbtF#ttlGl|m*O z>8?!Aw!9BG>e^=7a@$+uD^Y{klgFMcMts^S^e2ds*4wGEHZQVV7wn_*GuKZk>s0EN zLD~HW$Q0)6WGYT>dpwdKDu~(+lIe%7F2_!sWL#w505?(l2AvV3n1lxfo$-UXothqW zCJzs+={_7?se*q8x&MyhzY+TgMp~agtk18$?!wI6bxG5bpfwyf ziD#yrk>jk$Ib-ERXRO$ACN`2D z8tw`TNo?~QczY{77k3{ZUQnN0=*t)w)d{5%I+Ww=pkH-%ev8;0Fw%HZ4pT@PUtPX7 zJPaw+`2{1MlU1JAZ7MDaMxViJ`7nYbnZ}cE9{;{>{~n2yTWugOi6IJEBOb_X7X4} z06+c0A_4P0HgDSm@F2n@_Q%1q5v$-!0X{t=6@m|mo0h{9KULD6o1H1Ub#{B1`bWL5&L4c>Fg+fBoCGh%0uUe=b`hX@-eo9^4aBl z3@|FQitdSLeZ*Scv++8W$TekvA!v<*UzJzSaSkHMU(O}!5XBr+(zX*oPTSV_FYIc=e@1+om$`jfi-5B}u>9K^f$E#g^DHT;IllxV z>jR;@UsCE}nV7kK`kwsi2O_IV+LqOMUcbjBPf$)B1Mwu zJ1h_xj@lC+us@i&z92v7lnlbqatU~PJ{Grlx~I5wnw=NQOAB?;T5$sHvU%FCmA-l87h7CPBZ4F|OPykFJet5u{$)-54ZGz6A z)EsAPe(|npCk2X1rT*c=Kbe6DW}i~Dw{6Nk0Ln3=FHbpj29$#+GuU=s=5jpnis0H8 z%uL=4u>eb%zoOid_2XM?B8Z#s)t95;I?f6_-y+TCWv(r(sRnW~f)SwZi^V)GoR&u; zf?cWO!O2?Jm;4Op?#f4^V)4kEUXz6Ud{zHA?@6PY6h@ROT=xjxKXUsy+4Ws1h| z4kGW#(O4t9@o9eLOZi7lmMDv$?f84RC|^2QLAes(IS z`_gI9xioEFpi3$qWK;8D5$aXd(-UQFH!~hn$NKttH63Q0ud^+J&rksjOBDJ8m+e&`siYfcb z+rnA=dWpXTGFM=ZrN0C+x5G=BjF#iDeqLlHpTG)cew{LRELIm1jhLO;bp#lqj3pgM zPlu%ZTOMGasBVVr6LCCJIVE9!!~J--vMa;v<|JpI#q5hk`{%*T<%OM){W5oQ&O-jr zPYR^ue(i|x7~Cc)x|T*DcSTKpA~vhaW@5B?k8M4c!6Wfq%)BnyNd>%<@NGwqv%P{l zNi5vu4cMc^Z@$Eal&li46utFqoJZ=#ZEJqH7WLDpK<2LnC&|ixY{Il2Ntt~Ld8GQT zCybIbkSoh5KAmwlow3+BW6JDpR2_Dss2QJ>bMQ8E2H~B#zW@a^e|0fpH-pjWj9qjH zjl4JPMMM^Les78IKD7+syn z5lK)UBm4CZI(;zfex2hBvf`b(9DES^U?9t|u_XmQ#?tD5kw3!I_?;RV;N)>cahzX4 z<1FDI-%vUR_l9vOOKk56n|Ob~Ba;K%XPVN3&UH!h#PXqBEv0{hTzO8hZ0luOIp{?} zWA?2MA1XOib}G6bvH1fsJfa@?U7o_Ks!Cx!{)C*Jjx&(tj?3{Uc?1D}yIQQ35enjl z7a|6}ZJ$r-v+HoF&F5qodSHAdGVkgSOSkM>@rR{+xje*1!NdSje z<-|#p;slWgm_jQlwh|d^OXxuyD6MJ2)Tt*k9xlCq&rEMec`I*Er$b%Z=@pMDrci1q zE$(AlP0MYShIZ7JOHCj6{?^`W>v5u;WWM?L&i|W#^?gU{oPE|_d++tyYd_98D0s~P z%^E<+Kb7K<{nwRpwavE27ixm-1X%H3QyiXS8igZpJ!spG%{3yqfvWNmOhH0=*ckMD z^W-ZfA}$Q>A!5Yl)sHlyW=mH&lk>exBlWZb8WAdgljD zHIUv`BkdH;%s#acBzD!cV`gm)=6&RTFG&5@NLC}eHWGP&M2TzO#+8-H8m?274Q#$+ueJD`fENX~o8zHt)`6Is!N_Z}Pq58X6|ot=@j6Tv1iWx&;X!*^>R`3lJpg}~cZ z%hyX&u6KPFxlY}NRRikkXp;FZ582+rg0WO3TCl|7a$rZq0A>_%?|cy0qKkdkhv^LA zqo;hC2YkJ|72z|6JZSQ%8M#mYMylDWicOSAtDzUQkC2kD#?;Mf%zMb)1UuiY8-%3X z@d+Z6xQ=$gw$a8Wj~Dx5eUo+cVQAXH>!Dp7s9`q=a{ycYzLt0Z{sFawl1B-{=N-5e zlH3}AieTDv70xN!&Q(YtqB~brbd8m^tfQ5ug*->u)K8r6T!yqiBVR|;@jGe9EZ&3g7t;9+eB-O1+<`le$va$-PZNCn;*3gyRx{2W zum$qIJ6APP+hDWnK;wfbMJ`-|eECu!Oo04!`J{c3U(|H$pkED(Yynk8WL3FbFb^Tw zFiN`S&bU$DydB2{R8gnEDZjeDz_;LNFfITs;d8o}&I2b30`Z zJAU#Q6?8-O&qyC;;AAPNCNK5g@UEc-s=aEp){gI{n4BF+!`J1#lDcIPd$`74OisGrT!*8XON*?w_)N7{CC*n|)ui^x0aMlO~X5eD7?j1lqbp@}Xt%d9> zFd7Oh{Z?(u1PRO2{MA2GYFWyPqGH3PW6EDwyxbub*2l@R`o1K|(0oYEe|sN_-c`3i z&Ih8Z^m=OL)zDYL_||-NJF72dkFno)63RI}cMQ6F>SA0kK{Jvw7r%^o0yGN~$xe<+wHoWz|z+HF?z4I;U# zE{u69$?m_yb(sexPq140@NY^lnfn*1u($f?32dxNd7oY7LwS&a+AeXMleYU(Lls7~^ba7$dohMPF9wNwHmY1@j z6^gf!7c!WmS1f)ZuWNVw5LS-wzDY?`UyaHrmnb8a%jvS*IYSPZkJirsxLE>gXa)36 z-x}H$|1)xtr1CA4dsp4RVDeRpVvcGlZ3w0f?>uphY1fXqQN-LN7&wKxg|fL{mm<0# z=SK@@-SJ;ZByuG@w}6xf0vV9|k&8Nit55b2tvk1r_YjY~*?S%q4djCaU(fyGmv|CK zN~r^pO3_o@j$&Jv29&3IN%EoSsoFkKW#sja@ zP@(vo+2ije210>aP$4I4A4&An&O;^gIV-ZK=9X*1bSQ$}S~W+NCh5)9U!h&ubrfL6W`IM|1*} zrH$wNr0`@s5XjZOK|;Qp1_d%6h`dSHIZ`%Pg(8yZvs#hApb5`Pz7#c~*k_R@kVgE+ zG~u65{u2JD#Jj!l0zc135u=Y>*LU&Mo&`gq?|k93zFDqGt;Q29urwr$Ltk)Z;dE@p zuI9IKP7nHFdi!&zJY-p;9AE&dhWSK#tSt&|&~t3PG=c6Rhic{Kapc5k#VXNl%;y$2 zabr8w1o{pXFSkR@z;-Cw4VAnbqZBW(1D)HeGUbCvkycqqX+nxshJ)bamWHwv_^4al zWhqls3*6*&?ct(*{g&r<)TTWhdERS}JXJ+$10E&^$~VR-HzK!N*zQF~9=-ZbulZjUWK!qQ~j-%9HF z)`4i7cOV>S9q0|CMLSm_tXvtu5nj5TXeFy@-Dxo@l=~vay6BN9D7kR5?m@~AR|$ni zU6b#Evw}deYaTl(JhTddO&Fm3u>hVrLI-faTqT6;dys%iweI{FTsbBrNjs(f+ts0> zQdCSY_m0FM2o{`*ni)q7L}#W zlvfN)qFGaT|Eoz5c>lg0PA{HTok8Cy*#FFZNOV` zya)rJvs5;gO=|8%?kBLwj-f;oF&3)acv|F1TGmmFV0r7DhZN3_`StSn7Tp7$@1<4^ z)ErZ?dJ!|3{OlnOWBv}Q*yWBL7Ud7|)2zB2f6?dzlvzKw-}J5=>Z=A;sItIpC)UkW zZIf5g#PJ_4mc`wyiu*UTsiZi!EUx#`Q&&TTxqIM7o~<7JDP|);lnr@iQDMuCcUKL4 z=5n&`^CUR%2E&BW+?Z+s zR?qLJic~jI;?C+Iu5wk+qllf=^GJ?`R|k;6m6N0AgC2g}LQ9Z;bSuE(XXs@dG}k*> z7lA6N4xeN`on*eN`fYHJR1gzuP0hP*n=)DFMY&iPq49oG^T123SHY^E=k=TB+Q+M$ zJ2DA(lOu_ByC<=7hm{jxY@ew5=#S7uyw`yW^DcfNM-25o{0!9wW4`vMY9F6n-*?j8 z_tuQ9-(H---cy>0>2H~f&3HKRUNv6(9yQ6(I`zqAwU5u4+V|VWWX%e!y1kPZW2Wy~ zHg@BTt+P>Zb3a0^x2it+qRjlnD9H}=8tB3KChx9l`g{*sw}4tlku9~)13e@bsI@to zP9$Bq3`r+j5S9`vX_euIny)~8nz038U<_+VxZZpbt#v+yv)6HkwZBaBtg%^R@adED z)&bWpg_8BC8)};GM|a`!KKZ0;^KYJ*Rl*N&`{ye~4?BVkdE;f&MPs z{#!?)Wc4ujv1#Z+s&lsj)IP49EMg>bwkK=RXoTgppO))=CutJD7+;la-I7z%zr?#E ze*q#pFaRQM<&xDxd}eGzK3}6~tp5 z&^hw5GMYorDc5K4l;{^pzjH6(e-Lsl`d!bb-WsT$hy0IZKF+}`JFdymoz=5(BX<{? zDLG?pzv*wjg-R!{%SF(#+)Qe}1Dx1C?-NKDXvQoQu=r)qr@oP!hqE`w-}$}mKX&Bq z12$%`_NYp%qDl;6P7Ai!X0`70)bGS5@||8MUa>(FNgk{k(vzLP#3QP;OY8c-A;ib& zk#_VmV%M@s>~h_@0`?prr-qJZCal*j8$SpBzaAxxlO@r}_H)Pqt_{2jmgQ0y3>0tu zKc%;7pnU4q_DM(bS`b}?Y>Qu}Y`+A{X_E2NPv*WVL#*nbq73qH=V=_+5t6VLQ@wq1 zYSL3Ev9Y8?n%S&ArgA1{U=I;`UiYav8h5hpibBm#OVM?35txJU-kTxo zI)*gwvsDhVf@1nW&Cl;c`p(uWODAG3wPs8wBIAvydTx@$xBZzWxF=qx@*v{DKI8L| zd*B}?Ky)!yz%w-49iTbbx=+&`v~{U>d&k@+)BrC}k^7?XqA+3$_8)we5~Fm{uo$m9 zz-Vu>ZZon?KD&K#%18g6gh%U9Y;zW3tJlFx3*2a;`h989o*yp!YnsWu;pt?;yFFBo zQr2Jx;61WZD==BU!Zlg90apVV@6~kfQRlnXSn9fgu2)#d2Ctg6yo+(Zc!kTm_(|^< zX?kID64c*|i^avFFxmYixc`q)+=7mIy}ud5sKiiM^{o zbg`EK4tiR!wfiMxn4I@*+<;HnRr6t7pL`o$6+KQ6=ZK&ff?n>YsET*Hb8hY@>SPMj zp?fEg35>ohCVE~YM~ z=Q?q6>h+TRxjT@OTZcbRWcfO2Cq#~x$m+uVf+>)ictgSm%*#vGWFi>iwm;8zHzr+)S+ zkmW(8qSbfP5V8uqZ($3b)Y*DZ?teiDkYoc^Tj!#dpCH0@$cv^^tv^NA)$%&g2re() zTpOwW$9GUuMkjw=`|;}AfB;?m5CB~g#AQ3cSF0D|-yu1UhdaLrBItwhC-nf`lN(yEdaCvd zx6Scxf2!U)^`+V`G~>C2*?q0MW`E7QbI#n=H@t++m>-;t4J@&lSeKakWa|x?7@Xl# z4X1vHnND<2q$zW@KQLE3L}xRhm(u{JNHwj0TJh*p-^qOgtX=#v_%dt9_Yfz2vhG80 ze2SHtkGCR4eCj)isvR#UXXoBT2K1-@2A~^EI<~92`KPd}?ep#=Y%C;V{I=1%>*!n$ zUW$WQmjaZ5@35zyRwG4GHSqk`uaFa4xo2Q`sQ0cl`R0)^>b>s(eY(W^sSvby2mVJ6 zWWBpSJ&v2`8{iEm>;97Npz1ejFSsi!?@FYiCxo%@%Fzw-g+!B1Eb3@(m!uyVrJL}U zKJU&)s2HkpfeAki}%3|c>w9vSLlU41e%BhsFwjf zL~Y((EAq9Efg^a+3>ErI1X&#A{s5;?zu92DbC-8&?kln%|IFMmFbfem@eHpRDa1sU zch|eV*Gjo>dIf-RPp4j4^~2an)yKjdFvuf0$SxUqPpG_UTVAgr?^94< z%3pLF*nznCx!OG~15eV{<$;%*AI|qALS4-d|EjYmw7O;B`GGvPwe4E&STSp?c2D!e zzg!jSN$#wgyJFT$pi?#Q78viu9*fz@yS&?L{_P&{YhL~XleKtd+pD+`eL~!n!FJ3< z!%cx{Q}AH*O;G}uR1d%PdxTfk*12BnJyQEky|sIvjL&HqsQ&r$2sXEmI$CyC{|Kk2 zrX%e;I2l1SCt7xSe|JOvqwk|?qarN>6u?yJYScdQ;~DXpD`q{3ya$lw*=jGUL2_)_ zS+fGCwNLzXPVM%;QVDJ(dfSr!+kkOtJPz`XF>Fz_ytBsC+g%WFSeHM2 z{nN=i2C9G836&UiK3n}WoItO|&gvY_n%{idN;GXBwVthh36~HyZhQl0BfuJKdGC13 z4dY47Pl3|h?2XwZ_SO&Mu4m`F4gipl8z`uzRov~*xcr43o{KX}t3Lw_bRmTS&*Z!x z%^+^SCjVcQ|E`&o@-ung<;3jFVF)DFimKLumlE%2#>Cp1c3;(R##^VpgiY$L z?|o@?`_msBm_rj`F1bNux%15y$JE-ytlGx`w`cRMQ%74DqnPLJI(g@>;3MW;C98r` z=vN%SO=eX}`G3j%d7DsA4?R?2VY%v4YdqxRK78^GtlGU$l5FLEgp@&f^XcLZg}fZg z=_(Dw7%X`?u#<&+3cb#!byv+eR++FdDmt(cvDlhGZU@$yh>{yNj3Q)?#m_z51VLwN zAA54(Nu+~!fBO9w;6N9B5&^$HhJVBGIK!_o%rX2uL)X13-vWj!8Q#q>#_-P>euZJ0 zp=Moum!gy9^a+N)=X8zd;p?>w0}LNvxP;*d!!d@RVW{amMql>8?*PNkGyEFEA2G}` z6dek`p5X$9H#5AQ;XMpL#_&;wM;SiB@M{dm8Ri)NmZ6irbAn$z!$yWTGi+rTU>IZA z&+u;;exBhd!*PbcVpz3Vl{1&&%?#Hv+{Ew!hW!jb%kVhEQHI}U*u{K%gRh-iR5=$i zY+!gTLodTFhW!lxhT$;7uQ2>J!=Et}^pOqx<}hqv*ut=lVGqMThJy_EFdSz16vLMp z{)pk53}@1JNbsv?cqPM|8Lnfvnc)Kr|AOH@hEFgYW0+(3TZS{)&Msltz;GqQKIZe? z3_T3r$M8aiQyBhgldAXk89v4Ea|}Pj@M8?`Vd!IcJ;Mfua~Mtp72Q`DewpE6hJV5E z0ft=+Kg4hu!$k})VE9Hr(ftv_F@}#b+{5ruh96@XVA#s=HP*u>zLvtn-z!y9`Y2w~ zuy4A$PT8Qw-@@to`acQ>pI7C%Ur!OI%%Ryhfehb|09@?ody{3T{q>V%C*cTHVQb!rBzFf>w7h8tv@avcT$z zB&@ZOp3sJE(GZvK_jmSmCj5TB6!vm_T<;ZB?KPdfojr|ZS^WNZB8KeAp3e42M@X#b zjfUD2p$=u^+sbt#6w-1H9vIXxzkZO?f4sGUF+M!q3)0`6zlFxfJ3_Q za{kAY(NL`6itDXVcQmoh^84Gng7LWDZ?%WIxX z(A8MaY3=u~O_I_rizIt0YO9W4(z&HG5x1eA zR-YoiuPfLdI#>KV!jY~}Cs^Oy}>PXD;kWUM=qu(!nzkjACugq z>gSJ#g0c26ifIofpjF&Yu2Gerui87`3J2p>uqze{c2Gk?JyvITG!jEM(rB#_;rvK@yZUM`9M#d}}1uQJ^3zrfO0smvNvT z93MgJ5gZljr|Cm$k`xapl`>McwuYexP_nKrP(iTelZ>?@o9;nQA=YkeZM9;dIBIKc z?F7%02}{Zpx(D1_C7ORZvTKehxH%RIp=q(s;3kltKQBHXR5pj8Q0-9QO(8TFpTXeL|pHcG@bouGxR3Am|3^e7GV&CRuPdn-L{J7Q8DbLUsAR^x;Efg-PBh&@IRj`+MC;>Cw zVpYy3E7TL|SxB^qJn9XD3qrdnMm(+V35v>e)fxZZt!K(XgiAB{{Ze4cHB~CYmVxT+ z?}+H(4b?Bw4woX+iEXkLMSk-o@QQq;H1t7;!i)Y=(bcV%?Z$=e{+6!DreK#eWxt;< z7)9nM`$)#vuk%IOeHy{29|CV&*ywA<$@=LFh2zI)tu)2PH?)V{J&&|*Y~MyzBGrHi zT0xAGqBnzX!A~jw*aHn@%PaSVHavE-vQyI;%6#XtV25;4*5dzu$+RfBCkR zTn*`j8m%=eHhBHFwzf2{TeV)<8hTB1ud!lxa#_WC+FhjbsL7s96e3#PA^1KT6=Ep3 zzTlGJWOZ#7+jYOBdE<}7{3Rm{lK!yScdt(BH1ZCi5wMTk3cR{zVmtLco9@z|M&=HEEF9IuRR93LJpw&P|NuHuT zaRnHqVmJ#~$nz9vpqnBpU0oI;T5D4<9@5>8m`CD`Uq7#d{bVfI84q1g+_4syl!H*R zJ+uiChK25qhVsl7^v^V+Z4X(Y-u6&bs+D#!;o$u=3lI+>9tkF>S3!rV^J%C%uzBmO zI6A4W4n!Qth5#!WLw9aTws8??!!p!;g)T`=EX-R+w7A~ITG%;N%A7JPswNQDHEwiv zEM9WnWCIDXc2g3Sr%;11Dda?Jzy%!@g?dBnN%EbN5ad4}5l{%KN1`ECsfH`3eh)f- z$SX(@lvSWrMi)IR`q&O@l`d&TZ)ZXz!m-F!;OYJf{U5q?L_B`#ql)PTnmS#Xzu*o{ zU0Iuh2p&49N*HIghjqwGfr8bJDn`0xFNg9vH(R>Ma?;uYsD; zp2k8;B$^VD)vQ@7M;zCqBJsGo-$e>o$kP}LZNZowlM|KeamCD%DwcD_P{rk%btP3S zr2RXpSjcmF70c^!1y&T>BVApHS18bK3~p*S%0stS25s;OWw}^Rq-bP|6lBN!M2+T- zdSqWtumRS4g|+ZzrH1oyg(#VZ9t8<5n5hg55n6A;+SVEBqTz`&P%?07OxF5DB)S@m zmwhmXCh{lsumL)E*8-s5wIH$S!ylGqsXRsdgQx$G7Dqj$b{O&;{u`}QB^4Be%mdAf zcXot|CF<&mEuA#h=+Wj$*Rr{rW07uZ5Zn8v5CuP-vbEsErft@IiDnVr`~^j?hx~HB zQAUvLXAA8FJ&GneH+Olzl`xNtbOB3f2S4k!*&rlCVCg?6Oc2n}l$rg-)eN&fm*(mD0Z$~hO<;}<{)GBUVkUamxb9Aqyh z4|D1!xk6o}{VlLWxt!2L60ejm!U=xCo^3QA)QG7if0vxrRq5>*FM%SMsUs1UUQw^$ zHX|`q9%>wq^icIhMLq9=-YF%A7(-;b#OiW|SH+aqoBBLXFAXam)Fz=O&mTfeq=xap zT^mVA#nX)6aHnsDf4O(X@>^D~T}Aihv?j1xi?X32qQPx6&i1zlV;z2Q8grkGtb5EK zKZfM~O)-d`@Hh6Livg5!ASGiVz(yLw5v7BK*Mf*~eIiDxB!8r@TDWlC6h3ZFA_mj# zl=fXV3#{^;&R4{-i6HdBQU<~!ZmHkkvPz_=k0NHsNKQ&1){e(9dG(MOsZ;A&v~5;y}=+@wTkBXR82p){?@gWhWW=B1+sc*M(vUI9qNU~ z$Ax_zLetSxExN*|uLCK}g8Wyh)ghgqMNXb%3ssKWUpD_rxH8-YRC0%%u-q{V2DL7l z5~L%Q0Q_BYx;Hq@&b6RK`Mj>=9_*G@t<(?WObA_#N!4AIuKgtGm+Z8lt>}=*A1$dQ zU*`KVxUTgWD3M=;Tj~+e)r#u`MZT5W4YdtjhGx515A&uuEL~sH8;YOwHTfLGUZGx2 zu+IyW%*n~--C$wfRxPMqZz0cCn$Y)m$Tb5ZVIOy&>-vi%t_`u^Wx*^8LC7dd`b#QD z+GSb4OR37f3ysJ1nbu88*B#*yz-se)58@%LKfzFB52ii5&99f#`&xvU2~3XOD{BS2 zLK70dNbVoxG&x2CwD9*Q}*#Ag>b;kaf=HUhDCGszeM7k8s)A-EohF>ZciZluq*ftiR zvgp-lIRSkew4ElEY3@QTsY4?WDgmFIB_UoGLyva4A1SOS-$+yXUGbX>3(FO z8HQIYnvp7RBi6Y}8D&^!mi}X{(yUT+QIv$D2YIXc6?G}&Ea|s{5WEhkWW7{ZtvzK> zub=TadLW?kuoD0^9`IUkLAbs9|AYE6EDu={ zRP;;IzpXFNpsy-_N&gb+@FReX^dJV5YXcBe$zmf{ykdRgMJF%! zGXS>`pJ1jFK@BZl;K0;QH!WnS0S<*pN^lRc0KrW}f{9?4NTQ#RI?Lr2=oQ9Ga)k_| zEJ&$5bfn>=jDIPs?=1USPN!=hhn+b@)$}*$WXaT-6NpgQYsVc!7>rivM-zz*@Ye(fuFKO?9(YR z0?>imlT(_&Es2)lm!Uvs+6SVMRj5sV93ds#xLzvM`3Z;Xdxt9v#_3N#6S zIY-QNPBJD)KQ3R2Xr=TUDjPOS$%R_ovwaW)p;Cgyc%&?-FI~!)^!0M5KccoKae3Gu zQR3H2a_M!K(zul>i};FWSnQJ$6mh9xFGYC|T`pE2j4bUbmHye35A-U*G{!>P$-NPB|;)qhP!cUzW#fWQJt@D-rFK>JPQ2 zti~leK;^8}`<~UD0YI<4=QADINH)FWpxInrqSX$oV+hH&CW@1}92WI*Lg)Co2=l%{H)z z6o|5`T!6c1p)#v}b|FVDzK-f#wBt{2&wYr~4BrD7pVq-6_yXs(E2etI|9L zIZ8k5t{uU@eZ&B^(o_a%s9ZQBK2r&L9=n7!g?NC=t{4xrP}g73Dzxh?`=yF@SLXj{ zo`zgbfzoO<51_}R=t>pev|Y65Ad+*O&NmoF$-Yn`RP2S}*Rkr?xusAX`Z3%u8INec zuQAB33jrrqF_n8$q9^{zF)U^q)u>t8Tc!Pu`T-rBBHvo=Ps;Z3>3;O|nFJY{HWp_P zsa}Ojf*#GU)27>G5`!x}k&X$&`;ri7ho4hQEtzT$c~P`dLZ~ncpl%Db+e3{-Rp~It z(m5E6RJGfn@m$%c1LL}XSO21e6qF5#tNEy)+#p8%8DzW7AB?L3OtIgV(~znOXX8KU z$9Q48#9nnsAX{9h?-}Cj(z%gBgw0!tDE?wGV;qCtnfbWkEc<%p2olT0N?s-U(OT?V zh*UAQSA>}l_WhSM{!!yZTL4Y^(a73B6l8y({Hi2aQEw3v$iWaW)W%`CODt$TD5q&3 z!iES89`z`?sB}tSJw(GLA2g-+7!=rl+Nzpv14M zF)A-IsZwcNttMIZgE|$&0 zFk4Zyf5|NU+zgT9jJ;K-fbvS@)kS?}d8l9T!!Y74$*v$)H4)@sZA~o-0)Mqy zu+`N)eOy|q9KeU(71v#G&AKUP{|l3yNT)!aVpE*TUr?{(Vs1_KYbsr@!{`dI>QvSj z$@k*^0HR=)Pq|zwjYmrBTagY;1gUCjIoaa`8+U~8&_jTKgr757{#>6fVq%U;ck()g zPA|YeQhf^aZ6|$eE7wzS{ag&|8Cnb*7!tX=me$f1CV>|fh&DX7`5Hd9``V4_`Atec z)2|*kr}Rzf8$zB1IDZDv0{pu_IK(^Ob_h3)f1PxQ-{5$5$`tX$)G6Y19J8iP5iT4b z!XfY;kl~XKk$uY{GP6-W(zb)ff$3AkqkyZHZ)hc)=x-dNF@f3Ox!rO+6UF^&abKs+ zb-N3BR2o(jT~owF6>w4FEUaJTCbDUxh+BRnc;F9TL&LXtA7WLXRE30Y? z+Jpnzwa-+euG3K08qqgbh!Z%vBu!Wq)fM*z?hE_Ol6SW=FMJ>{67tM+~W=;_^9e&|( zP8H5&Rrx6}l*``j6z_hmN?e?nCC&%WtDzr#DIwm*F|wXy13u!uzh1Z8LwpoR?*`PndWxt< zz3KY1ICfAP_*i~T?Sf9*@;d6AqON0>sDo_kAe*{%=Vv9o1bC5gh!l=-rdM`NWiFX1 ztS22}J`Sndb<;%M8`DJ1Gs>PQy%C3Nqpo9(yzWHWTuMV7>3->TSsvUkrSG_Lnz#}C znh7~e*^|sSI3aV$9Ws~ohW=-sL!F*?h{w2$(rbrnnsC84xWEV3qS;x+)9Ip`@*&UI z3l1@=^OamnokKp98@TNJY2y6XoR9_bp+1>0hxj!PaXYmM_J?}{_rz)Uz|s<2=|7f{ z=4;tPC!rU8T-VB6=tHcM1LGgGENhhm-)_(RkWM;rUi@@us9 zwQ?NCrL)DQ9W~-o_>N2AJ1$*RpT96WXY7Iue5$ib$UY*V{fE*atuwBlIK*}wFWjN@ zvh>>FgG^wnweShG&>QJrYM|%P|C&WJvglKMijGqZBEI?s4i^GE((kfsY8Uh@aLOSL z;m~E3UOQ$_6SLPj^V71bKa=|T%z4OHBeJhM#FamHh_Iwh{{B4hvpn4~yGqQ4ADaEB zGb;V%x+&%T9elt{@_n!y&#xWgb{wCV^hkGR+R_j^l;B7kK>KH|n-;zJom0gO$6P_W zOMcr0^`{?!^U0?`59=W7I>@?i(fQdFa8QB>|JEU1#X&JA{jUEVzQl_|U$c+*oiBa7 zDvR=>wc_Kz`z(%s;=Bo*KaS(ueEmOh{ve`cOVMrI!Ebg(sBqImCUk-Z&?i z#`RGg!#JWTyvYp^Ge!I&l<4B?7H-8XL$JH!+9iz`r(^DLHI{e$3IUjI3TFBDk$a|y zJYso@8TIdFde;=vG9_u3<9$(mNXwO^eHUqIq*eO;>HS%XFMoP}mg2*o-k+uT@Td1@ zDL(vHeSg**cw2f5lV3z2w>0%l(YxjSSiYbK1TmJI>f44zcUn5|W9|~0gs^hojafKfYCf$936SAjM+ zi&pOo)ua9F8-#e3bKen+A+r#39VoH4-OnrOlq}n}1?h#nvT3(d3Oz4IRl!S$ecM{` zgtWgozMh^b_G9WYL}k;X9aMiT)pYxB>4|LZ@nStvyo1ZRB}5I3fVZDS%4)SsOo27> z{2fMMtP9JgM`b&Z8 z7Hlf!T}2PTcD6%aQWY+PCTyUGf0p6VN52#?g6(t4S2m2ENc?{mr>vCc$jV-G#qDfb)PTh>ykK;p-Q zi)nj5{gFY!c&=dy-(IrXn?B99?+=k3Von$oq!iX-4p$6w*;uTWo1ymUyRu>LFVtVP zb3{^IiGB5&sh~Om5IHb z{?&18lS#;3p8tR}?f*WA{SiW3%5ALY z-OX6p>@D8GB0N?QOIq6;-?(8Vrpfn|q>-!8^4deZ!-9>n;$*S4*bKyuOe`g?5J%V1 z3yd(zDwc@yIV_Yg#9E?MLdrowL$d~ zLhQzs)HJpwAwH{9$aRaSODIUu3tzEjl81P+7J1bewYVijt9hZroF>4d21ehGH7kkX1SldaPTa%_y3- z#|4U*&=BP{7o#M(_sw7IzngnHjNla?C0kV% zQKQpj@2L`FNFxPO^8AkU7gPc8RQli=)C2Z_euUoCrS{ES!F1Md!y69xxsFd1TTsxR z-<8A^V5!uh_fowJ{h=!LBBT#D>a>D?9d$h`Pps87M4N|#R2$iWg> z6eT6Z-P9f`#NQf;+?&MMd~LCw(!D-dyk18S23}9~qYScY>56o<223I9N~5$(@=^2` zm9Jr1d|hJ)`S1T-wJy=MJQ$_NQqj}WN}TuurKu|EU};4U-b5ipRWq^6C)FE!@JxFLUVc$Wvj zgG4cNDr%w>hBkdQ$7yReorxt5Y>T1(Qz5r@V!K&v8wn>aJ~fqWlit<#KxjR=O)os6 zNTIeZp-ssxcvMo?@|G3r)~;w>yh!ofi5(!z{c&tl#9Iy8{fc?u);y%g6CHAMA@y=t#?(gFgL}5iI8X)lXjP`8=JNdav3)fLU<)vlvz} z{PzM)AM00r#X4ZVcCWg&(@R~c%Eyec{Ow?<>F}i(W;|U_OjpXE#>?>iybVuIVggg+ zakg^?{a2{^Wq#_A?a|yEEX$_jNgWzJE8@$9GEI*L)3g`q?Tnexaft_~&x^ zXUnJW4_~hG``%FbqYNi(6*2r03T z6ix>(w8V}nevuXSy>{LkvWjC1+7C#bne6WuSX=QNAw6A*S4QAjt1diV)RU0piW~mv zUIcM^j9yNowmQp~=HW$(c+FL3BpI_BXqPK|F+EU%m&b(?*z<~63jh1*O?3L=3Q2d_ zHf#-4`Jl>&|?dV{r z*TD(B`wCAIf=IA?Q%4XlinO?)$8`y&5NuC(4%qmxSgz@5dEwNu4h_JIr)R^{daCUq%KB=r-U7hG}H+HPN-knul=_@`{-Qd2ZwDp`kv?VZRz$)-`CF#Z}`P?!xJ9elcu1VuzaRa4Zf<>eRJ)pBn1o7ir3xf<&B>1$2beRpNL1^j=h zTpzcmaz0Jh<*j^wOz($xmEX_A%FEH^N55O1uIq2I&o&+(^=m|iW4|izuWh&gXqOI~ zeU9Cb<5yfgMk>Q_wiXkdBR``hfpO3!R! z`r}{Pg&)N@&cU1NR_WZ7ItNbZjoT=$}Zmdj4 zmv8qcI$!?Y%K7wtS4ZXhx_(U@cP?mD^|Qy{T3?-vmsqIq%14W!=1`au?4Kr9D!e*f zkcN!cFs|;K@YJ`FvFDTdm0GRv@t98ekLlIFqVD(Jc;<2gXTj6u_HjGL7N4bDu3wW^ z;k~20b_Ko+b9+sAy4*a+HQ^PC9v-17|8aZASYHRPRd{&fq5Q{qZl-6#)8+PYJmzjz z^zdXz`H$&MupXH3G`%q6g>O*w@RUjUkLfjW+!Nq(^}Kxnnen_FpPBG77{7~ID z;c0qV*3;4J6uwEX#&x*{JWbEb_K{(KVDI0w-{||6D$j(c>7|)3-X#kE!gB5v?9F1i znea3{i}kdg+hNi_H`mXEr|IQc|J=8z`q{@(y1i*V{$cx|XJyNNtOsFkuQ1^0a(zs% zkMT@=9ytr1rsw4LrdjVzd>%gwo~9?b9qHwYFYhU9EH1dcQMSwaYtJm-arVz9JYBAn z^)JtSF_r6MJs4&?GV!mT?Zbqp%N48#oPn^>yoHQCy$;|Px)XS02n>}`z86$U(A?ilN{kNbTS z|8ne~O?aAKmgBsr!LMmO&9OX8c$!{6%h$#6i_69rO)tysHQ{M`Zr1w%+lNU{$Jj21 zZ&vc4cgB_d*xp>+UibB9)`Ky&UlX3L-vqZe$MrMGL!1Rq({pjZfU ziS5JLr0`7k*2em5!qeq8u%B#Nr0AV*kjEI?n+Z?T>t%W)S1Wp^_{GWXFyU!>Bh2Ss z)<0AIGTdGho~GBwdfMhbb9+Zw4@`KP-WcP#mz=r1gWBEPJcd~ROn91JJ?lZ5$Bm}(po_~j;c0q(Y?n=}_on)}wVoRAG`%+F^Dy@_ zrZ}vD>u18#^qN?&hS)w#^m@;Nr|D(bU-_7xssE_w`kC+w^cXM8{$-BAej8YBCOl2A zf%zBZ@vlj~K5nlGPt(hAzm?_jk!idi<#srETw#h&eOx~io-VhZ?PHwn+%C65{K9%Q z$ole58~-$3J+~vzc4_jvSuQtsjq(Qz4D_7b52jh4P4V9_(=*}e_BOCyWj?6NHPvs3 z;|&v@rq|2mT0C#D#MBP%rv>YasU3Nin+Z>sn`OP~9Nebp7ht&a*6ElV8iR9hvYnJr~!nf%VU1=N7lugjb-) z?HJ?!!|o@wJe({y6P~6w%I$D5pD(cSxj>KQmS#J*`(2GU%Jy4-^O@~qkoBdH`&Coi zlx00N;puiXFrU4w_a=H?_E#o6P0!2adRcBJdSh&FCcFYYmTy1LZSZ*dfO)t&u z2y>ixkwI=@=CcV;(;H^IQTDr*f!;9p`!4Q(?RKg4z~cI)xqha8W{~ySgs1E0V?Ix? z-kaJx$ogl()AUjt$7XL*dTP>p!E!UtLJg3$#1y19VR?ozZ~m<#r9_MYrR~q2~X4OXT2Zie!=9&Gwg>< zc$%J@@fz5Vo8pM5mfKn4-4y%DL5|l<{x8FN)z9Uc^s0^NnecQwhS`n=InFlm#l`k( z!qfCzOi!?$n)D#d@<_9PHmx6xu%5bkp4FrWIp(toPuFjP?ROvhA=5f%J7v(PUc_3S^Us2x5I>|%N=L=W(?ya z?Vkr(|H3>kYT{p-z8A`nD{)wdX-^)vB!0KoZ@9W8fO1unr9g1_BOFTf56rbO|OaD+sFRz zDg&O2+hK7#?D2u7XL0>}*DAi4+AG+8O?X-!{akJn>x-Q)+7EfS9VR?Yub2DPA&&n{ z^3AYa4zeAY^f}FX+Q57^`9CN33nn~WKextXd6@i0R{MJco~GBpdJtedQ$OwFc9`%q zy$t&`7wezNPX<^IOn91}U_QHVR{CP9pPS=E6P~7*)^^15Fs(DCSr0M>JWbEy_NF+l zGp+ZGa(hj9nqHXYJIM1Om)Y!1>vM+jeC%ILdY@-MWWv+sdfAS~xV7T{zsONas&S%|@fR-=s>oegEF}-p2yY_OmJW||_KWF?gw3ybeoMl`QV7+(o{J6>9#+fe*7|$e+Hr9jTv$R*R9%Oi(?tM1@ zqUABd_S?&NZUdg)PuqHy_GXyRDb@qK+_XG~*e*x8U$ytYx_(~Pzcj}icE79f#^i1(fn)%$uanqFseF-q0w@J}6;pMqs9c6!N8YlNL zpL4ADc7LziJI?$Y;(ci*|LkNvaB;aN`L;1$ire8awU^srvA!HkMm2~Wp;FAdD+UT%lIT#Yx#{2OPzGU;C%)0@ry9&cwa|MB>InCq8ctn|R{H*~pPwxbc& z0~21J%N^nQ7n9$Ja{o5OdT;9Y8<@`)x7Xx%N7)}l**}}?V~FYHS+Cw-&XvMCryr|Z{@s||ehS_h}{j>5=XlNT*R&t%WqYeM!4Jz#~Y@3I1iUw&+V|wLzg?md=9YwneZmKeofrJned`)A5relO?bWBjvU7? zCcBKXeR!BJcDvMiHO}%KzE<(izF$SRx1aI)4RNBz%W=6A9EaKaL5T;Wye+_5x2TpEp8^>3t^F3%$PHt}l`^g4_UAAfe!g^rx&%>;Lg6+sO|B_<)4mGLvn&z9_?8kkqSN3wX zJla@KGpzTfc*xCoVUC|ogy&>G-p78;?l%hbSYNVi=XO7& z@uJ+`FvnN(40@X9emcwXnu*>J)61}YuQ1T7XL@tEy(WFhus)A0Rr+k|-#m<$J4+nv zWx09I(q13yvzPm~%MI-q;&wzCZ>|B)#pU*Ld}X57%k+HgPfhb&{p?@H*xpR>ft&d< z%yFWLUY_w9Sno~s8_{;odSz;F1JiSITwtOq82 zb}>CK>#2!ep5<20<(lH0QEo>+^UpN@?BV#O_hzNf?=|R4hW(X?@vbr83D%c3manOP z{p=5V8P617Wm&$0`&E-a9npHq?KSZ)#r|)U<24h#QSJZOj!gXPWx3_qj!bxC+>T!M z&!%$oT)z?ar>1ew2+J*Zosyf0&%>H8JpW>)ad_)u5x%(`BO)#F5{f6B? z>;8P4>*r#5nD%ej)XjLQ!!5oj*Faa(-Qou795Sqt_jV*so|jU7l#IT%N}JPlp&F{T@LteUlmQ zwh`c;=%w#71AZEdWRKx|81OI*DUI{eZwb>kg*RfO>kCLH_ymqT;Q;FI0u#K`62ii_ zE(vzy@ZubD7TeH?P`Q189q4%IdzgKI`uo2G??Zs_QKS?6IgZcZy!2bX^o`%0R|)ZD zq!aufI9|g!-Y+R0U5L*I(>dU`G0{02-|NKt8%6UX)CcE2zzs`OI^Gv4)?KUc1Ar|} zsy=wnq*!*nO7{USxlyI#{XJsQ%_`jkIM<`n-GG-bQ|WHNIV~#P0=!_QO1A*3yeb{< zlM_=usM1{oZ&B&c8}X|(DqXBan{HL9>BSGt8}~{Ph9>HmF@3P6cA}Ss4ITSD7r_!^4ElDA6Bv}A1+p5xifS-RrrQ>~; z;wKM5PQb|n-uW=T4UKcWA4+@&#}1t1omnFI2_gO*=XgJ)cn$}Bn-%Z$5^J|B9K7dD zoWemkc-NR%vjg9^#5vyUD4xSXbnvcAaoZyb2k$=>KfodB13vg?D!mUd^htFd1-$LE z_{J;p1^}o3ox*nkhEj|V_%;su4l}_yd+~WwoD*D(<29V)-S*Rr!AvWQl zdPV{N>6rQblN zZy_JT;Q>Cuf5Nc==LBEH(SdVNixp>MUx^PH706L$>_n)b~fHlwH95{H#xCqlZ z@e1$&4w5_G0WMB)dLHn$e^%*u*SC0y&+)!)u>=R@#XGyjVH}iKJnInaaZozmMJ-;% zLFrk*_m8S{yi-~n#39Q9oaA)8Ls}$oP&(c#Egr`~bns5)!grhL`^}qi>_hzt_Tm`9 zIo<;;9>*c^0rmHq310kle5)Eb1h2%A$9WX+$csuJ@XlxPiEpU$LBM~+L3J1d{4&1F zOuA9}eP;Tm^R+KK#B6-~nBeu_bchC=6YR&)g7aa(O|PiDQNWRJF&)5n;@iw5m(uS! zmwvCAzS}(hD%u7*1gr3E<;QSN@NyjcaP9`&jbnt$0@UAZF8vNOeUJI#?>ofzfkSXH zjw*b|nBc8A=HR^a`^xl9<_CU=Z*U`>;3sf+a87U+j=OPQ`mJU92Jw+r`~>!b^U`lB)3=sq{S@s-I>GC3ypD4Z;1_Vb zfOC8cLj2`Phxk3tOTVK`-&caF_!+GiVlKgxbkh(neqaD5y$Uw{$;@MB>WD(IZSW>2bDDf_)R{4 z1+WHRNuhKXU<;oUypzxG2He5t1pk`PKLhxC9OTalE^sJ11U-CCa3>C`=br;!G)0}) z0}kVuL*GUQe1+2q{(;Y3Q>Tc#s-}n=fpa(D5Dwxw!B_Zv9B>D|72OIP`quRfd?%XP zG8=FUjxMD40e%8U0Ou({`kr+d=LG3{)nV|8AbqQv&I!`@rs^Vl z^!xuR2ORiblc1xoyoUI0Hxk?x(q~j5?!>)-m@59NJd?b-@dLfxT^2r}67P)k+%*5{ zM)!Ox)PryC;Tx$p&Bqr47dFke@X3^(j$ju)gZK3%558PZc^TuF29_rqN&zyij zPyD9&$ym?zaeN)LI~ZTs-Ps^z*9YU>jrU(Y-@+%kIyd7hR=1ayMx@@a zY2l(m9shrwgzuV@%qRAV{m%Wa{q_4B_V@1Z+mC%^g4Wo4sj+>+gFX@GZO5X=dXI_Y z^~bH_4aeQbn~ozfItBhp2v2G#l}=?+xs-FaYje?Mv?)-Z#2$Y~T34{64Bv z{eEk|XTNv9Z-01y6g3;%KeT^je`bGne{R3?fa`$!K+}P?1Azm52l@{T9!MV;J}`1% z?7;Ye?16~`;-K?j_+a0`^ue)%&a^Atl=h^(=|FlS?K(7csQz&DaPQ&4!$XIM504xk zJ3M|ke|X}s>qz~Ph9mAHz9Vf%qDOj<3?3Oel0GtgWc0|`5$93sX!_{z(S~Dv$NG<@ zj-`)fj*TA69?Kn@V6J$MdyfZ>hmZFj?>nA4o<5#AK6ZTkc>egrapwuwiG~yI6W$ZP z6M+-a6TK(WCo(6%zdrb9@Xwoyrg~F-ss2>`ZfkeLZqIHnxJSIp?H1sYb8qk7!M*kS ztbIe0GfGl!@TF~kpum~*{^9+j`^Wa@_fPDvKVTj39Pl0pABci8L*PpWT*)199&{aa zA8b0^qz~oIX4XUJ@tkk61@MN4!VE;3IKy*wOK$6Gz1{>sZ4v?=hd$vmtPp_?tVHKjwnYH68az z-u53KJU)DU1bodN7bl#OtG*L$;Ar286u3HiV(diz#02qn5PcSSTc5I0o|HEg29F1! zrz6nQENiNJchl}R=qu@JdiU_|vEAdlC%|#iRnk+^(V;!5J()eDdvbg7dt7_#_crbI z><#P<@9l>~hWC!_9p9VXEA~0}HSBZmBW)&KCQT+i&O?i}4wD9-NqHhR!dN@6j9#3b};*j%D!y)$}-=Vfc zy@&b^r4FSJjUF01ls_~9O}7qv4to!Wq4A{eBZo7Gvxjqsokv{I^d@L};7H$*eyQhU zN5+p#91+m;hNIr2zN68jy+?BmwQx8w#ffotGItKR)?-|)Mz9+j! z>~-#K*z4Zw+uH_<>D!yyo8CLRcWiHd?}W4-&pz+I@V@B2LD4I3JR4Nau$4_UAwFKj3Z8ybQQWne?OL(ao4*iaK}C;%JkhYbx& ze>8Dez=j%NLq6$?hK{6QL!+>v{1MmDdf1Q$HWY>p4Zv&u%Ud)wYwfRFhQ43|J%NRu$qRoMMK3V4KZQPE6n#K` zzw1Cf`T!65fUxWXhT-YR{|k8k26#FjJY6q5T?(FV6rL^*Pgf65=YgjS!_y7I(~ZE> zW#Q?Zhg`6sCfHB_Hq;Lr8ioyx!-fQGr~x+QlfA|eJY5E!E(cHNLXXh|PZxlv>xZWs zhNl~crxQn=upu{Ws0}vM2OCPmhQ?q+6G!Xe={)dsVR*X1V?(f^jO<68$6c~tZG)%l zJKm2TWLWkf6Yz8vJe?Q4M--lJ2%atjPnUzIgP+SFu7(}CQuVMR53DGReq<0eQQWYiHrXqu;OR!;>GJS&_3(5ac)Bn=-5@;O2s~XDp3b?~1uJTT6$M~L{jj28 zSkXAFNT3gDfED>*MZK`16s%|zR+Qi8LT}xK-a3H3x*wiy7(MkkdTMdN2`h5LirQdB zeXyc5tY{2YG;yFFp3VbL7lx-Bgr^&Ur^~|AIniIc;py7YU-!Y&rQzwu;OQpd=`46U yFFaioo^A-9E(1^JI$U4qiK6I>`r+w@;ps+UNhBpF`#KM-sSUCM*Z%Ya2mTL-3a1JH literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/errors.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/errors.py new file mode 100644 index 00000000..7bdafdd1 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/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 .typing import display_as_type + +if TYPE_CHECKING: + from .typing import DictStrAny + +# explicitly state exports to avoid "from .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/fields.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/fields.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..07038d47f1c6547e27a5f5979a93279f0d61f908 GIT binary patch literal 391168 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 hD(@^ll7E=4Avfw4ejVWt_^3Q$wDSgl~{c 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

  • j>Tp-mkiP3&MyjC0`}q6ZZ3K0M`UE)pZ(1xvw4Fd zA}XAS{5wMOT!*w5PbX~+`gylB3T>?iKc-&9UMW=jIN@^qZ{^K)VaAqlq_M}{+~Wki zM>6oXQkSj~!-&jj@|LnVDngp8sGmjN(*)-PBkvA^bBIWjChx%Ci;{Pc;gEFh8@rTY z=M0z~1!l3LVtM8v6mDxyUu@z5B`;&o8->T=IM1T+@w^&^M~lKICOm}?a}+LD;Y8#* zDkq1FSi=%#~ zixaQ&T^!CEOtf5u6Oot0bn(@@jF08h5g$L>g(gq3CI_m?8|mK*EEF+wU)h*5tZ|h* z*-8#m$)n9w2=!%du&bIRfpV9Jx@xwF4P#$|O^T5dev=w1#yC~9;MefNrDvvvBhP5n_LDF zmN4Ntay05GHVi#yd-YHHr8xipm~Kv_*j3G)V#Gc}&3)QmoM7p!eZ)PzFya(|we%GG z!L~hD#D|q>gW`hVGQX1&$4zOjQ~wSAs_ed6|MfY)|L83GpBbCm)PJ&FJVIw#|3N6e zeA>tDrv1br5_2KF?)&?x^;}(p1wsDdZwM@Z^OCNWD7#SN_=)~kot&taUecS#S<0rYZ$+ElEXrA_t585mP zXNKT>2pla+P}DjEZU_??D!YiHUh}<>B#X~od-DQmLXD>xlie*ie*sRPwVWKd8m=G* zUmKPC-OMFaegj;;C#j##Y%wp~5tLL4i4MLQban>by@I#xfrZ1M2-LX@YI;uj{->hy z(2J(BrrT`<`gB9}ae;0IbQ;7_#ix|d?WQs7t)|NrWX5<9PXdA!Uus4_{SCcKTjGm8 z8|b|mtawKDGX}9YxMVk+g=sFyKPRhEcA&h8==KjpI-hWBXGYlV=^CBELlcLFFpspQ zS9hzS9eXHMAr@8kjhh={(ZM`(3?c_eyX(c}v#E*A>tTP~_2P%2-LppVJF-hEnikR} z>s{*6zJi8{RJh{e23N7L?5A*4_OuUPr)qcx`KgBd4A-078!E{xbln*(OtQK&*1!;& zqdW9voFMUx9&|TYX7y!+s>bFSgxIqac}pIQx#Rj0jt(c-!#M43{dpzbpZB>+E^&CM zC2|mM6|a%SZNFeO`tf{SEb#*6B+y$y+t_#(U?Kr@=&xmn5auX#?jf;jZkMrnPIOpi zC3^T5RJ0Vh`=z%6<*~YDRNs(%=b8Xb6XdCxrax8F1Jrb$DlQOgDGeD4@sa`Rh>jSR zO9ryv4Wot|v>(l6>J@w^epcMpI>>=DO`$_*=h*|)PJTwCr3=8h?v$&RxBEav`TXlf zG2tb~Y^LL_HtM~ScfBl6jNB~wJr{G}BH9H?KDC3Vq;^x6RWy~TEnS6O-E-G)RHujp ze9~6WhJgQq3KV@lgFYw~*61bOz`iOG>eiN7kM$!foTqtI=r|D>FE=ok;F`_T(YiUP zZ_s!}Q$+2q-(UR2E;;6hx^Z^8)$3miWTZ8<-ToS@|0Z9X52%eUnAnSEAG0!{$MBp{ zQ_YqOgGA(4yq)Pb@1j(n79*;e3}0*X#;C;v0r2vL+FdodteG2p&Zo~;y1&H2wZ*=G z?yKyoES-a;8Ka%%cgTU}#%8WUy>K3IdA}%Q&7Me8rPZ_^sM0fWU!?a%+OW5wr0t9B z*m#C1x^9pIEK}EmU)>=uu&QEO?kBg0ZJ@62*m$Ou+s~I9M>!X590z-Eju4ckJ~3*- z{NyEm`z1|AN4o2+Ub8rd*_1bK>y zB8vmR)c0#VIHi8yPjaZt;Ed_jXRVF*EjGq(>O5WqcV~_Ct0&Pfck1j&$@J8@?{-7Y+@Xo%4lFrl_y~W~nX>!j0VpHT?Z>xBl{7M^HnlnXA72rcb-RAf&i~${@Pa1M| zC`!LqshErCIh0Hz8YQ*F!@FAW_AQQR!#OmWHSR}zz9~e9W+Qr@A({~2+W~Bd9-4({ zyDUU^FFCy3$Dn6^BSgs_EO3I~VfTbdk-`k; z8=`jz@HYY+XDhaBud`A`t(h^@_0~*K_fFM)*6M~viw1Bu{l)UwE8uMmbRGTUczdH( z6IrII86AE}Fis?jK4hk{o2BJ3V+OvSKW27lc9zi*i{7eVNX_9m8#rF=@v!&-Zl+}qkRD6a2JuC> zNS1nYVriK^dvjuGwmGqssZsOA(*DW#lmMMHAHAV=-l3iRNk&R09Nh`xW)w|oD|_wS zMy}76HmP4#FCO|8tKWN?ZfolmdZ!=wmi9Ca+JaY8=nIl4^pRJ1h5j^eI0>4yY)?c^ zqH^-V8N$&NdTHZD#_MedgJa0Gb$zC-$5_sqL!wF5eOqMKJjScF_3F2@_1Prf){DH+ z)(qFycq%8$X$#qqLn3HvbG3EbUe>RHj83pU9#|HYK{4*9jI1$T~ zF%|?On`O%l;s=R+2M&I>#J7IBpPgy*q3}ojEK<@jw21+8!^x&j+@0$39 z%t-5%8tA1Ky8#+*T5O*}D})z%^LC2E~tNqeg>9~o+;p`8p`*+&96}|gW z&eQuq3a7s7?y$GZ=*?V4ppZA+AozB5tjC8zbe@uR?ecx$6KdiRtV

    eD$2)vly053OP*yO1`NUZFx&)EH<=nGTb}7n)q8E;Qr9 zahQ}Snv{qMDbaENi4q;84%|rt|A`Wn;`F^acH10Ew0$~y`uVv^^l$)^rmVFRRgzeU zTa`HHMf7M@;_?^Kqc!|vdbB1n_Ql?*ow7tmYmNpKN@(NX824h{Ic3cM|BKc zTC)a(V@(mTcUp7eWC`N^nC;SB~TuF4FSGWM@V zzLN&MM61p&8u|SD6kf;n!kNH*3P0lM{x9!S7)>E}pTf)L7%zUGLWc_qUF~kxN9x}d z&T{|z_bL3s8j8b9PhTTR9Ned{_&iPj0dvg6F8h(Ebo6*YI+6PS<$VghVBBCy5jYdv zeF_hViE-n0z4BZfe|Pa@hfBj3-b{^T_{)hJ&^`=k>PP%~g)siJ`xLU{8QeEe$`u3L z&6BxYp{rf4z+S5yr;!F+up~VDH%K+ViA3RDT}hLWi7i;JmoM^?l@U&c=oh++Wd8)}M^M6zSvf84e`)I3YlAi@muM=7zT*V>5)Xu#{&lh5gr%eGUJ#N!{g+Z?wB{$k|I()u5%q^|uFV`L{`{g_y z%RAL>o_g#E8I5&&#TNVojz&&UZwuQMjX{IDGH1^B4;ie z;5}tNmZp@3v)QeEN0zYqyjtF@>}|fCtmolJ*=6x>^R3rU)rY<_^&7k6%>3JY&*ybb z&TYPLG8gOs^qT*NyEl)ovbg^E5xt5_ym7fUifB|+w4x}YV8kYnz>OptMKms86m3(t zrb=4eV@Z_jV_K}G;#R5Fr7qRFebHzD1p$%89ko_md#`b!)&l@4g5!JT8lEluEh2&MuIS__V-UI_kZn-#S``4?| z^#e;q7?&)NILg+MX52}|8~I($FW@(g->>;O*T_eXw9_57uaw_^NdJgm55Kg0%&gZ1`d947thc6r4Oqy^>GZGK;0p@_`(EuO z=at`1*KvlZK`Pj_+Echz%ZIJb!6BilcWLe9C#n+zE~jdoZ(C{nOQTzi=4S0^Zq|rbsfo!u*c7+Zo7`8Z&aulu!LV*A5ecHCa?Y9<%?Xs1Z{``F0DErXxzayR<#~ub zd((Pi^l*C}+i#+%yP1yQ7NFTM3?{=bodR_3Q(-doh4_Vb_R0ZEEWMFfR`^&XyZsA)HLH*aL z|C&%nE}oWJZ^|UoEbY#45QvB%-gq!=7Ejf|{SpOriJKj9)wGc@n-ocnsk#c&AlA3| zXC3zwbg+vFm0o%zP=bHiU0G9CTe#HQb-3mIvO(W?z6!~YK^Xc7O3Ec*-e|(zoM9J z2Aa2ih0t0B?IycS8aWBP)tWz!(b>=?Mi`uY46Dak!_wply*nEc4%+3hp;bKBKgaGy zsUFq=ndmDb$Dhg_m9c2$tm3+2SaUm9qh`nbl|ra|mYHiVoGmwxU%eyCOw#Z+69TR3 zzLXBy$WveI-e*PRbl^oh?j%z&3af&KoP&$2MAg>TggLY|udeghzFBSEYc`h)=Wqim zb4G#tlg=pWQu?u1MaV#$K9Q{w&as7r9%T@8AJnqB@*DD90TF)~Ul6hI3T;XpL(y7Cz6j@KeSg zIfPawud!`Cp|;R;J(8f7)_Y^`PfBw&(yq5_EW|7gCSKM3xcayQrMTZ-G5A#q7UgVu zA(kFwd{a_wYOAsIzU(WErH4z!_AFf&4BmrRW9gMAdzN0rLz<sks&IxX@EvW?$h`&zyf4`8jqO5l zbBuGa-%`;kiWP(#Ew_SG~3LW8c!& zv=r^Q)RihrPRlK|uP^l>mrq+yK@@R5o?GHTU*c(%;1=GvA<3WQmKf?{mAunQ|>#>;LkaT)`zyZYO}>*h?A3L?)Rp= zCGJ4cfmz}f8#zd-nudZo&bhhEmX~Z|oe4eRHQRX4hTWU&yLY(m$BJCC9B7@#S}<{X zJa`5$_|bm8w}vPuJTsik2$}bYetat(0+LcHD`J29+-qWcm3}hw#n;qYA%Xfb$zi!x zn?d9iVZfQ?2J!kTBXw9MvNX5ZC~hCnSZjhFunTp z!aa(BYR4s_y+h})=^}+Yx6K=9sv-NMN;a-@$-JXq) z7}c-!00l6Y*V^E^;57W)xnuQdZEp>8L!b!EBz8-~lr}_x^tNgo_X8SY+AAVA(v?^Enp%z0n17AEb=@H!+>vjo@6NsI&fV;DgcvkA zd1ZM2BM6-jdZ(_YBQD6pQAdl5SBnM1>JO>G&Tm4s8(!;Wyvqn$V!8rFVJOxE)46yc21_9$~4o<&tsV}=A!!GeLj@lvx^_! z)j*NVeyS9VYg-?=bV5ieZ0VjNDIQ%Vgx3dJ-MIFLt3e-IY!J^a;pI{a_?^@hsa+%m;!R|fryRV_xI%fo0sy*eLKsE%%{(~ z=Dfu40KJP|vuK^qs-4U>1sut(b#F)T8w~ufDE@AGlcspsw5E@zcw560HQ8Ylutl#; zE?AYJ_}QX(x!F~9zo&^jJZcpGFfgMXI;AM2_$x^j>A+vIUzd4`NA;>H4ZV0)IF6%#ABdpTk7});oa>=%R+ngk@*P!X zlmAN@@?R0ElWFqj22b@0BmXbcn1lRXFV{Z;_}cz z@gx6mBxL0;@&vJWPh^QroZ7}(-{i=?_zroDYB|hting7)(dlu8!);Ri(cg z$M#zZn&RadEr!ghXJG&G!r^y9M;BglmmrEk%o!B6`qbb~(aHlop+bfvEBE z-q?<$(eU&I@PuFI89}uDaL%)+vZg^4Hg0%Lu%Ir8y$8KvW~~bb+)K6kil?fA1q25m zx3->MXLFlbbL#`0b`0_;AQQ;KMrCT?0Y^v%=In*T%L4y7 zT!Yl+EZSaYH7X^z>G@8_7uEY7w+haVx+xXXRG)VI3nC9OXqjq^4s@TUuGZh48ttt! z9Jm%*XV{A{=eGYk<9+0oKXk<%o8{gIJ^8$6OHH2a34@Tt=9{(F+7UTu2aaJY&7j9H zmK7*#kV_*AXFPF^bg?NVIr;_6P-2V~JM0+YXyjMitW8TnXAc0Ck zLXhxR5MeXNzG38o!=!#I%>8ozsR7M%u!aszH)kBrJ)vJYffB?hHNhv4r^T4~EZVWX zZO}{lIi+1%-3{!jZJFCl3R=b-_>Hu>CfNNihw*SY=D_QCNH24fz(1LD%>-i0+)>(| zCn5{IR)^t$0&BsZY=IkT^bkPDSK?Gux1H=Q$ddtTzLHFDKy9&rY3pNP!aH&j(JnL^Wq#)Lu7#>hpmp!C}{#G z+J299%9L{$CUqU32hU-fz+S$jtlAdLNv5 zzfSK1GVj;uy+rTF8T`xj{>?_|_w)7sLFWBjy}!mgq*azYazEQvmUd0D%Filu9+}bh zQ*HW)eYi;B|)CLx^+aj2K{CxjiOE7b!_@bMlrU9*>i4kTFgi zQd`kxD;^|48@NhN%PrAgCH~C?($-x7Fg2+dyfzUIz)s43mh5QzM*L5aCI)>Xwv2Vm z_ECpsVfqy7#9+brEwz21lp`pTMzkw(po*Ms4X`R|q@!DE6Jt3j*bBl)Tgwm+%v`k! zA3|ZoZ?hBqJFqX}ek@40zPoZ`RBjtrP8t#&Uk-`zUCrEbhpXI&<^t(`@ZE zDt~zSR z=q%Hf#T*Mix;~w$KE2Oii(UKEb%g+{E#Z*+B6Jn!e-x{mVs7S%d|4haV*i z*aA@98#{xcF&EnttXH#P-QyFQG-QKH;gRfH%f9_65=1vm{&R4;HoN<<_C@L1vh%B~ zrb4&gMU0|L41h(ZV&2%?sfcw6s3de_RdomXkDSRshq1|! z^1}?=}V~GrE9gWb1H7wp*b!D|<53tE%p+)FF-ctSpYf8I$;O#KWkmiyYg;Av_6AvYf> zSlPxn)XK6ks=%i5ccb-CGaXJ{)Fz>2j(|sO#}V$}^^k==7Xtb8*&v1)Ki~ z`Ccy>#+^Y(^xH`Evft>bv*fjt7)`@gJ2Zo z!V#=Z($gBG7IH_Mk}`^%Unr3)oTWfeNd7izFV@2fe3 z^q<4C3LWMPK_&C1T%-c>6|{{F=VH}aB?qdcZ3pppr;klxVI3-9SGbE^jXFpc2j)a! zumj*J=JytVqi>(&Rm7JqZ0WObU*MNNjm)F14%|EnIwR9UVB%kZjn4x1xwb={vE~9` z-BkdaBw+5;r{op~?0^s$O$gYAS-|da!1@;e`=x+20;~t=_TdK6_RG}gY2U6lH`y`hP5Fhs7+W@UY=AvhTEJEs%ij9P_PzVlG zCX5{N0)WSiCCZbB81`kdfupzBjh3b@XfZZE;lxQ3kALE)Gba71Z=dn}4&_(HZ#chw z_=Wtfh(fSc-N1fXjDE@cZNhKxhk>j4D_dPKU_4{04N{Egmp_r8jP32?aUxEee&Kh5 zI#A%flKr#(Hn0z`ubAK3ueKu9x_*7db8N+-^i3@;`ux-g>>+g(F?}z)DtO-c$`Q2B z%3-;A#%%SPE5gih(oD25IrT(M9#HxPd|T zXxrVYULBT!^s#!?Phbjm;*s6Kqy=Lc9iFuv^u1?oOBaTk*D5s?DqYU&{o5tdwN@cT zY(R@}YV!kH?MmCU+qR&4Ryg=#Jdj48z| zQuIQ#1$bGWydIwmom%?K=Amn!(6v0dVzJPb)cCn=u8EuZ)AZ=})aVYiZsp%u_*5Ty zSw(kb+QN1kud5h&{K1Hdc17&)M?zp@EP7rMJ-v*gp6t}-PHOWK!)UeIT&^~;0}E#i zy*BuVMm;PX^}wp!WZja8U8=^shWDu=_*m7Dr5J}gyFv~jAM zdpZEchyMU(wB2ryq%Rew#uUZwBL}5-(gOCxDFACXV67h5?*ImZ|5|}W>r|9Shv3>^ zVi}w>WiO7{*_$piH_xQB*R0S&kQG_Un#V;sYZPmDS#tW5_M*C_`6uK?Tb~(%M`U_3 zO?Y~@7@iEn&eqx+yV@`eJ3Fbec5-?smkPjr+N5w?JKL zSh?O~%g}AVFC93MVK6eG-9VlqOr%p*%ZM3B`z@$Aiz4ui;LFO-g#)augIu!45h; zW2A8)n#c*bW}(%Y>BT;c0|e*aqeZ@^5ON1oZa^)CCN0qMVgn?q^$^8fX5(%)B(0}I zdmR{Zr1No!frdu@idPHmNS)tc9Oc^C_=EL_AXP@j4Wd_sdHc5xBRJXaCr6Lqbs3;9g$n3q zwBr@2>u~9SN8DU+Cri$#Pg=4GRm9yI^xq=lZV&nzYSfpjLV*)WWCuE1>ttQFq#qf6 zzIcB{qv1-CvE-UOmaGpJ8CN3DpHuIWny$(oOkoxP_FCK&EXCC4A}kuV=$3(K`#&Ya zjjb{P!yxqEfV!&SAEB1=M1AlHsRuJS^H3Um+yQz@e^3|OP(Nz859->LI_LAmbqq{6 z%Q*XBXY0Oc+~~STuN$UdHj#kojg1GKFkeY;zK6Dnq@?|kXgawWu7#>L>>I^n&6VEk z*pC+VX2_BBQKK3y-_Z{3z@?Tpm^jea^28)nbKig$Z5+Z&Fj)Sd1&e^TW=P2VUg;BY z#p7HQDPGizwhn3CSu%(1i;pIC>XzaUR_2rrL8|6HPw#pTshazY{vJ>@ce(!VT{U;E z{_e)iSIvD)k7YKrs<{vG5{@lvRKJ?!WzRZLspKM(z?^S-IXJWr!xf;#%j}G-)*0Np zb?6vUbaRjvhHcmV(n}V!X>1Cv;k13}^m+G#!~3M{o=;xNn)?;MPoFZM;cM=+2|Nx)qd67VyrRePB~2~7?p2S$)Kbkpy}aBstzax$C{~}&d8-9bii0} zEP*8c9!E`&90@#jQ@fm?k|ld-4>TuW-AVp6YWu^TqdQiseI~$gZD7z0P&e129WQpy&^Ml?(Wq!H@k4bv-iN4mR&3SM%UvT@AjT z*Pcn#x_>_&>g$4Gckqx7AKGD*kYrtXiyeSpR~mp7PYgcEAbmhY9URCM>}rUnLb621 zbj)dT(fv+tD`FZ-9rc}tc_2`IoWj!XE6Avt`zuW@ix49<7gEezCQhYHhTF8ZgVO7e z#mV$nq|;x!nl*&>UDS%w?oI*CipZ7wYDTz1<@OrfdO|p{*Epw?70}kkf9hIt zj#BuN6zw5%7zTQ--)nG<0n1c)A$jtnHbxiNDs1*jHM`tKlj~S11)0EdLF@rz5DZiW z(FC96^v0_Igm?ObAUQK^WTnRE17@;Wa^X=Kz=;fCh25zBN?WF!0lcWy{TKhI0q90` z!QOI3@}@2g0A=*m)_zrUZ=$^(tR?P1I2@`wSvIvr>!0D-l$5=y=H5aL!#1?D_p$U) z6BzAy$>=zo#FRK>qh z{9cpOU4Ar^Gf8_)$HCD0RQOi%sk|wKN95j-Hu@JJ(=43sP^Be%_d~VP}*k`GMgc56N079Z$g$Pk3xue zZd3bbW+3b<2xqAMJiQjJ%|W_i;2a?8dtGtuNGffO(2k^i;Js=JiE4Zo*rbIVz{FT=D$aeFk)v4s zbC9OQb)}ZB;J7Y7Yk977N2y#s|E0Afuy|keBQ}wW`itfL;KlmnmX0e+b!yF~@oCQW z-6VE=CdSNL<>HIltzojXHJiz)aPS9Lc_DBVK7e?L|4Gc)fe>%AlMej@KZQ+?rydO6+8 z=?nETsarf&)!nL>BYd$5da3p=wdTfC)=Ln8^y5}>j)XR*Jb)^z z{)bauM{(UtRY*!3h5Dxp{e4dr+R7E$sQY>=R8$L zpwAF;G5SsCFXveCfXk|P4Q%7BJ~#_KhTv(=KIiAz;kG1~qCMQekF;=`TX zw)hQ8nS^->Yc|RX_am+0wLMs=(B00nx7bxkaTVd9%woh$R)>)>mEn?MUm3PN?nM{J zI|mP)L;keh$i*XMkM8Kbs0mZVk1!(YJi(^>t3elNr+m>q zC_E!g(|IAYOJ>EDQikYTk(|+OJLHY#jy{IT<`SGj$GNybCD-r5J*LYvv}xaPFe-Z+ z8{BR)K$q-J!vJ5cO`a()ov{a$(-}Dp^Ouqag&SOiE@bsB(B_V(73`0r>M4@9*1G7F zvw`Pnhxp%pjM;=07XZ3sCy`3U%Tv&|Mst8Tf6C_iLd*7a6N_teQGxoHO)}-?Nn6C5;rP9gjeNb||%U@vmm3-;7)(&6Gt?(EXW}k|G(Hmi( zvrH~^fukfzFHx3`f#&g7npPWso%x5O*h~A-)+Gx>!V=Dtj!%bK^84`|`7y*OCM`d< zz-Z8YDacDbKz*3D&(7+(u!5i)(xLb7M9AV(>W!T7~?f;fy;bOXbk?@YCj48ve zYb@RyYo#$5y{C#Kz7Ox-d?mA!wbseqHFoCiQgnT6_eyozM1)kS831)IBeR*YbfNyf zkaIq9Ukg~OI3V&Ixln`Y+;yWeDop!ogNsKH351M`CLbD9?_R3zg|g&%H;*Pu4sK98 z(-zUO-g3#3S1;NRhWR(@B$v|iWC`&Gfs?Fe=c_er?gotzYNPsUflY$QkvnSWc%We1 znxs}L7IP6ZI080(X3CagVE~LOqk(xe&~sqCVy)QtaPpUA*m$6Z*%^!2Q7LSE3Q%Er zb}Cf7nu^Tm3_QU?0M{^WDECo6pqaiwS<)Ptvdd; z@i#4;QtJclk_BQQL=#>j##sKpV)AK*&1hOa{gU2vkJYq)3kW1f(*OXPeEQX{k{pec zH~r=a6?)tisz?`lW+xRI8WuWEg`5%;syG(|#^l)MuFyu^lPM%g7x`rSu&uLq6qxrx zlgYv}R6>&O*>s7f0V?rSSfW)WB@7A)Odu)cm8QKl9NKRRm8PfEoSiw_$5 z>Q84#5o$)-4V6_mE$!ZQbLljv=8Wbv#A!|kqH1As>5P2Kt}iX`nq;k@@p7!(081Xh zeIXNhFF+3|jabfeQ{{BpA}7;kt#0(Rq+vT$87`{*VPKmTa?!-)P9^l1mSsmJXjx;W zWi^`8Rx+PX(ueb8R`BBFFtcApHt-TAPs^G`J9FQqGl+}lh8-B!FeZ_6+$ZQC2)#KJuQJ!TYw*X6HycmXtR=<#uM-m%b6b;3=L+c5QBH2PZWK&dSxrJ> z!t83I!X)?{ImiBq2{SZOw2`C4OcQSBcQ3y={8sUsr;JMdhavJP@!(P7L353dz5gRo zDqq9qx;xFyijSB%h{mGrqtv0GBb|{u@oHDH%Mi$l zKrkT6gYa&y0{1aX7F{4xYOpNM%?GmAC1UTIH7+Z3)hjZ{HEPmPT{_mcJ}gasbd58b zdT#-9f=#>c?7U4;YtmQSFtG6A{0oTGs_x2T;hM__GOj%78|Qokn=P)c*ldz-T%R`4 zmUg+CqgAtknnmmd`9>Y$X3{i#i>Rw40AyQT#hZN9P(rlg<7oTe9bPxsCym!7!@=u8 z;C1!B4zD|##9rg~t?uDm;*o2gotKv35}bG-DqFd)cPrEFtx)oi%`^$<1cjwFLSW z?KlO#>B=hel9h=aOIvDaiyJgQt7r$)AFBu&?5hL-aTP8AXmyZE-AtXr$>Q=pldNmd zsJd?_FZ+}0a&~_Siz7(Y!ADiym#Bxw3KDX?-{);&T>fnk?Km1c{lm;8tNwjki@w(~ zxYlg|+Vv{6Yl8Qyy8oow{Z-pOna1amo64+9@L3zKtb)m@i>H*-*BIkrxSqX)Q8T39 z&ScrAN?#vH8px9&y)M{wC9nRBu4MZic>WC?feK1_PE$bzGYh!u0Vg&P#6;w1AVLMd z1AwStUq=Pj*e-j}7<>81alWy`t+B{BUL{cDDUH52)`h@OUp8l~Ro(M7#{G73a~S`l zCZ=Q$*CY+J-t0@1T8Wa|=%D!${VBVrSH`TTA7ki1y{DV8tFb!K+m+I!MKjiud0Nck ziu=NTXz$+Gey$_Yj=RfU^GjyZyvo!C@bTi>U=>z&u1Q;Vq-!f$;qDkYu=@?DbgdgD z$KZa~vte)SXu9C9*l{I(p$0Wk)e7W9NuBl5F!nG?Mk`*Fkw$fwes1kBR?Dlym`U=W zWbszaQ7_nIjvnPXJx5nVI&{_#EV71ew`bRhz^+R~zGYiygZMMGYvtkmsl}ulf2Ot| zQ%t@)_XENi(y%)Ag412W)CUUKSj@;ebcy_01gIf9Op1BGL_1!vv4rMaFA!1_7$Sq4 zOLw9j-BtvPecnfgZY5o+7KdpQh6hh-$Qmsn`WWdDMm#*8m{ZRaa zQMc&OyRAGPz5=4cz-*;na(W_Fwx-RNMY!0)VN4rjUXYc}i8pp4K!|ibOLtBxh8>IV zl>#u(J`1Ni+!?ktSTOH61!CZyAKpW$Eo5m|WQ243ThmA;+U{ zuz6aoc|tFSBD&tNj_d+-p<`ofU=54F%HG(81%=%mMBQ+;Y{vsR6T`JWcsF_A96L5@e~}O;x*TUds(10? zK71D}h3Kb?33L5Z?eZ8RrIBv1G0G3GfXF|9LjXnMa_iP~EhX|!U9`OujP3w<l?Zde88YOy;L#|G7fSk(t z6Qd(^>BtRO0K7>3*cO$ML#smjY##frX>HmxJ*_&|A3>j(*2l5Ygwwhq9XCZ`;noJoO>47}L&*}U1x``;7JUXq zVISY2bkvJg+D2?4+-OdR+C_+^$=f+q7WeyY#P*gPIvu~dF)MDNchm!$2*IX!IBUpr zcAX*jWcp!v7N)#iWlf+)+pjT?l*nV7uivNZVv)Qp-hbmY&OLp(WwAb8#xPqW94_}% zpp*O@wCI?o;_=pgy}zGMr5<)$v4e!Ith5r+wm~o8ypSBU7CT?smiDTGvE{c{w(dMX z*>~FNjc}rD-Ka}yM^EXrwSBvKdrSMw>E%6Iy-J~LtHtgYm)B04hv_787yR>xh5@O% zzFsSiN{k(pJPB_uryNDwZ$j@4Ns%F#RHXK;j2wz&ZGjY}mW=5qH~x!I=16b|pR&7M zIDtP5ozh8i%?!4ZR0sbye_QjytBBmdl((Kq3x7dltabr>8_`l4g87oXEY~i2Zyd?h zko-R;*e#LK_Bo>8qWXkgWwwq*J0v(Y8Q>k^o!ZIi4VTeswBshj#?c^Z6mfp%O5@|);)x5J=ub1|>3&t8&CB`}A#eH?A)$V!@HxOG z!~pHvyE5$YHrC@J-|2IguYHd%qVY_Rd(O7VzI*GO2(&i1;0e+8_n1ngmXrcpcr^`& zB`#P)z^r*-^JvuHT17!5T4pcPJuXrG@A4#3ank6!MgUB;$d+chq0o>&Z^$as8BAbh z2jdLI313B+p)O}_pxU44D~=gsk|6f8jnw^`)$w4uEL+hXE9u7w9pgvpD!y#xBikt4 z2pn977x%nFz;Y<>m!+(`{95~|-1;z)W*hmtz8szTi|=#&47RAR0KC?Y4OT+Gn!1YE zVH-2S?eb%=*h;Q_L!V>vRvWznB`rtH2D4UEvKM=Xw6AD8%tyWDrbqWa=g3*=MX{z}gSE6UWuGT~YyJQhSFEXqPT zuH<8w41M5UY}+D5Vk-OViecA5lH9?R@;2VXji;nd_R{*eyvkTSP-q?F|))|hX9sg%=;hnC}nOkXdM8J6ec&Er!ZmHf5xMKr| zS5pA#85I`lM~c4|&Tb+8aYK_W8)G=QOU=bgr0ZQ;tLna1`sgcLU;uLOH|zbW%=?3S ze4=nZkJl{FV?IjwLgKyJBw2E|+Z=e`eb(gCA2tHq{zx!UaBZ@&% z2TYvHajcRB{ykC&q|&iuY9x89RsDb-;sdzTU@ldpz?=jh{FCcaY+E9PU4i=Qx`b(z zqedt3)=>n*Y5n5jdpefnC$M>%3S7Th>S1H@%LkmY{U|K#Vlu4NhGvd>sIUy1aKi>N zU(Ls57R#NJWeqcJ^0|jp?cD7dP{UpfNRr$W-Y`&;I?ljNk;g^JT+Duwx=khp%qX${ zmMCec4Uw;Skj(T(+V^=iBWX zWH1`@{qV5~xkZR9Y0QVVd+ka(wQ0OOx}H@Xs0rN=J8hcM!)66{JrXOYUF7iRoy45 z=7z*d;xCwgks}NAIglb-;VNe=4{hft<-Jq3v{u-FrWJAu+Q(Cz$1ia!m{T_5{h%6D z&ba=r;V(;8eG+`d6FfDL+Cbz0Z1Krgj9$)V?nXBgmZq^TIK4@NtC1BuF`B*CXkJG* z%eByKT&L)?4x^8i5#cuFY&=-~)J$DaL#q?kCN~AVuK#mXLMWK$HDk%?O41Is$B4|1 zp2P*PLLAautOrzzde*_008}b+O+L;g3rUSQ`=PE+M9keQz?zcwR??@I^oCDTWXZ1o zSkgkD)K5w8Skft8wtUKF#3!BPleFn!6Yt86_le82X<><}?0TE}o-L|<=DlRvN}AgB zON;L~1dk1N6bSy_*k2>=zDdx)vj49n^zF)ggJU+FZEeRrH_22k=CDy zYjovL>h!6%%dFf$P$O8_x3xCY(=UCs4XHL|tTsEHCCC3B?!bk9(;GDzt6`~DU-64f z#SKny2wsL4eOyKpGfHS+4MVg{c9v}I!7PAja>0C=0aNC|Tv`MSdI-BtJlmEhXS`)I z%n-OID`bC_0kI1pQe&vkk%rqL9%MUj6F!%fA$(BtBi-8n`5hu(Lb!+5aEDj{=ccYO z$uM9a$Lwx*ce#C3wxox$QnZ}GdKeJv5`)hoQIZ#fHLJPXjvgvWcRr0(>9Ci^CL^La zh}_Rirx0#xD%yN+Y!hZ)+2|CE1rgo#HN&au9;}gEu!#t2X|j{AcOg*K4vo`P>osoZ zS!ElnY{}z&89=Ev3Y@#}oR*5Wyo=*Db`8Pp_v!s|StZs{9M zoglPVME*sOq8;<-e{E3D{;Vo@e|8%gGVC^hgjqZXi>f=1G21Si#k$0U+G8+&WyKRW z%+??5Pnn$>K+CjKs}CN}*`}=q3$3y20o7{w!~4n9TkM-G42bhE4Jg~<6AtEgG~9VO zmfe;wH3w!>&w<_`=&xX<5cExTE2f1FwaI44TRXYl4Ux=DZK7_Gx9oBTu&g#QWl>pj zyUfhyKs{bi+kq-Gbhbqu30`3PMHC*o0aP0-K=vctKIn}-ZqaJ=>65?mJDbl?^yfz}6gITE_(T?95yyMtLVoL4{pT)JXK=~c#rWxQHlR4*r zCxmP&g0)5sX|hlSf8wT!3DBXL$E>Syi7@*j+mIqtQ!=;IbWTN9sGAIIkK*YvjU{${7yvpo+)Jm152J=6 z8y>_D#BGaPCpyOX)&@F5-QJOI_r@+~*0SaA+g+~6Z&kz{dM-_toF_P|HT+w$;aH)U zY@wOBSbO_Kqx*Q=)bid~s=%GXB4XT&wzoLR z_TXA1Tl-{Q%rLS1GuM;2P6_inGf$oA0^M%cA|gf~tU)%jahyGGr!9q7P3 z;Fi4`+4Y_0mdR|pNqunAp!(qFGh3W|Zn=Rr`Svx;x0>;(bMUQd#ln{XIW>L8{JY4?FdtGYi_SFeSZ zoQnAG%f#rdw{zhxd4oFO&m<*8-7F2h}sYW8Z~sb-}5#SV31>;K{1)Cpa4Idd*mO*lBWsLr}%# zeHGNS@wd$|l>l2o%_`nk@ple?>0k}S&oAIJcKVbZTfwQC$EkX1(GzWRNT-9kfWVCj z1#hgG&EMJlUCG~-MXe)}>qS1xU`CTdlSy$)A)CvFVr7ek%5(;if1#RNpp6%kUvqn1 z2!g^xLAXF-QU z?SfPzUdqpX#7cC`Jc0@$u-5AEp@9q8>0q4oS`V~n)do)rUqdb8$IjVtKTLuI=MD08 zN0o~_;{^CDGgnOo0KsEZCoi$z(inCY4{LLSGQ@ma$MtaX8#@FYg@W$-(n(yL5U5HQ z`z+f2g@$fHG521ZRc?eYhrK2%DCTj(OAxF6Fso!#B~6iVK{4$fgYH2LrZCQ^7qj0` z^E5ihPT7$z+NYJX)?IZeK`}4F42AUFMN4*vk%wn^GHGxsHJw=hkae>$yy(J61z-i>?rDJ*>IsJ z`{E6}A1T0mf?cT#J=qt8@-fQDh_FR1qhaXDE1(y^?5aGq*sd0Dp+$Doi{)w6S&{%! z)tr6^`s86t<^J1)2O-lNFta}NBzlV3rnqayS00{D?q&nP=p@Q~_&J&gubE~d%{Yp* z`vQ6XvqLb2<3GDni)|3;dxodaj(H+GnIm6`CnmJ;QRJb|)+K77vk6J(B+HgiPO?qa z+~P@0s5D<$bAg?(nD<70kl=&{e$eEEsquu{D<@`ZOH4{LDQ=T^6a^XZ3DyW;rKTF7$Z{-twka7=(uM6v%0T2~8Ij;{XXuWM z=d}l-EP0ayx8#Fo;^4>TtmJv#;D%u;+!?!wKgo^HayX9HRxFg$QrKXH8r+Bm>jF(b zc;FO{PbX#L0MW~5uvaSlBm42*Sm%2VR*Pmf3)V=%>KZF7Xy2Z_(Nsz^XXO?C^e!Hq zNi2aZ*AW%qQ0NTEB|DiFi?Gd+3eBUKAhIt{SkAws3sUNtik6;o(o^b_Ok$DO^%O+< zQP2XeQUcvF&LY#gjmBLceB*FETHW1@?uw((eYjJl4z$=oUTwwN@QVFIDTGSq5Dy7{ z3g2_lA)Z{YPQ}O~#YqR+fbKqAP#+p2Bus2+-Pm-)iHkYOlrO-Ai~Y75M6XEd=&gV< zhR~V~OUTWFU*_RY7W|_PK4$ick`^dw$}f0$or=V5X6v)4W;k1M0*PGUVHpb+f%S92 z+QeXq6lJ#$9$qc60J8XqT{yO|?bB8Ml^XJm1$v1J!MXJC;H#d#JZT1VCXb`=L3Y?@ zvoDxf-6C@}Kl-l05KQ&M;}u7gMmr||jDspzV67df zc5sgFzF}@Sf(jb`7U#AEjuS;~yrf_xVC}-*GoOwI1 z<{fgwy*wqaJw2o%MkMWJp=km|l~xgbLuxw}V824M(T+A?OKl9c$#MuqSM7h-71Kweo%Hoxq`_6h-pZ^mye&v)N8UDb0}Ct6?|7KCrgL_ zEi4_%W=3&!OI$ce=fxJ~lD5~1IkY`0(09p%U?yVA$=8I*=|>LySCEsK*e~?}5io2J z-TwzCDxf_B>Yl6TZQS!pJ#$_H3w1B#8Qu1CJkGkdLwZPEF{0eA*0#DbnP4elt83*Q zcK8l+EIw^dJ9G)ZXBmf!!oCNw-?NsPQi*&`F8ia|EA~VP?zfSpCm(T1 z+**&l^rdyu@rF=Yo!r z-{RQR)t}PcpMZ(fG~h^(#BG`2W7yn-H$&@5PT(4y8t8}L{@(#eS!NzBT6QGh98(#`@8;4nqTdSXmtaxJwJ{IC0}c`Uv#Qp z?LTy@{lzNW87rf5vj0ytur=&etV5sRde`00Iy4`K`koH`-uyr!hi5vp|Hr;V_kW$~ z5dHfLucm%1eTPO52s`u`Z>S%as&HrQbNZFMoILQhIz-XQ>d_|FqkX==M}6p#In43> zk2ej_8n+#?(QPAGn;ERPn27Hg-2)H=)+j}|>5cVp_(!*30GQED-eSD8y0I*t3Z`|AqTvcg$ctz}fBhpsPc$ z^6WrJsnz!Bv=@^%L1-XwmHO)uc$wh;$lxFK{qS*FX0Y|Eb7U)hlDB!HezlI0#-NqR z=L%-DyAd^OlscAFxiNaW`1>2-Os)w#^6kcSWP9t#Qs()4270}1yei8SQCF_-7s9e- z(rO|Ptp+rAPxh`gA5SuHiQuz{KDh2ix-ZZ2F12+-K88e}x>({6cXYfWvY4i$b_-H# zIfrzsw9+IxR`aL2b9CR}39aw=Qp)rF$7nx~t+WCUs$B9}tmBe3O*W|RA&iD89LUJn zCo`vhQ1ZDlfntJ10!D&nwt|==K#DjBF)+jM#8uIb(Y7EPmQ(xdxgv57oo+o*L&S$; z+8dphe9=a4TI>A~)>sca*7C;EpEhssv-A`r_AzYByDM$pw#p1~UE=d?wZ;%Plk+F4uh0gLCP*C!p3oXRaR??D zRK?!D>`dpEbETW^CX?BiMNJ#I0{6P^an|hh5Yu;)3tzkSOW^yMu!W_$(zkfoVO8I#`HBE>cIRDS(t~(BnEFHWPTI zxQ|(#b1$Nk)9V9DHt>s=)+RtwOOib-`n^Kv!L&bv8e`hG9I>I-OsetY}l6hY{92`F60eXaXLz z6t54yb-U9K)%(iSdBX*y3H7$QT!ZBU*JB20lIXQ=%x9CHlH*Fw-8?(JjbyjuKsUAX zG9`lwsirwVNC6XcF&_uAO`A{WR1ty(5cVEZtOlFB?zck9sVlK&$K_kY&aV`rs!Xk7 z6uq%2Vsi8toGN0s|3l+l91pfke)^~ur72^GH)M$#TTYMILEGVB^{ZN5@gloGqvxtx zu8n3V87EMN>*HP8sj4I0mr40GMDBW^y72PLG>af@l$4<#l-(gLyTn*gNdMvhYE?uQ zP*|6gOE!Iladk%iAnqhSu`wz3!lOve1+gp*;vqm_g*bOLUGBt+P9Msl%{h#D=(EXD zzj57&7wN`|G>o&=4V$H0blBu8%uWGwaYW)>@t_1)0u)V{!*B_!Y}=s=hz-DNxw-=i z(SDOZnkMW=+aKRfjlFKyqyB8q(vgMjnlibr6kLyL5IsOZ06};)6n2JLzV9tl;#CL* zeQdThDg0LN*i{)+MBBHtmc#og)Bai1HnO#^(jsZv{?xYWc;q&8Ca-%v8tPt4v-H%u zVA!M5Q>8eMUWI=3+vB|MHHUaA$y(%r?N_a`U-cnwf&nYknoRr}4F1bUw7sE$gLTY%t@52GE&pauv? zW!H`{qtYw8H*C^@<_D=Whf?1@jy{r89(PI^ZGYfLLXjUD`+o&k&|owycTlma9M1;m zd{vpk!jcY^GPvaDIVhS4oFZ$ZxF`6iF5oi&ImXHQa-GdNqDPdM7bE(}0FGIV;ypQ@ z8E%{EF!eDpq1ARIueNP^-~~vo_ZUx(xAF!#?x@0@u_07Wj&BUH<;^&kZ^MrB)w+r` z7K=6eLMiKXBQw`WE|RMB!Vd`X5$kzH;$gYS ztVquW=l5(Pz^!LPvwHTq^~UvVtAd`*hh|*QHu(OY^>>>Pme<%9NFJ?|MY{Dz9qB-# zlHJkvE2C*Pq1t||P(`Xtrbh6R|D4CR+IRw7;dl-b%aB;sp5AW6!(hDENN^$;1(0Q8k+aETQtYlHaT4wB8 zz?)7u?Qbwe+1e4Nc2#4n*Ve0ROmL0L*|J1Crjd$Jic?bkl|<^C*`Rv1=X%QZRS9$y zcI%To3xsDny2t<4(ZD(rcC_bWC&|uv#({2f+ns3pH|A4~#MksA&Z-E394$uu3rNw6h%$-(K>228RsM|g$uF<%QTkZJj~8qH6tX9JkF9FjT&JCmo} z>q5%iQfV2W*!pdoFnn$zHNuiS$A2BigEh*Yc&C z*&QX>Mq>#=v6Kwi{Tay+TncN7F>7i?8orZmjj#utQ4#rwaKgds!3woe5&8Q{-WDO@ zxG1-bI=S-ge3e~A!_&X?WRNG{z-^=Y)#i?E`)h=bx!W-87<0e$S`La9^J*x%`dQG> z_ehVT1aF||4i)Zdyk13mj~e)|pvOq;Ci(YW!6U<#5=L&@XXpuSWg)F>ZMp7Hh9 zy{4bvzOm~`v}0$i*MoA7x)^o!;$B?4Gocz7eIs>YO*4fP?Qrb$)ppHg5c~3BA&ci`ith(P*ZrOL7UhWqU|Snj1`I~LqIKi zV<}y^=uGQ3k}id#{nygWjJyNhOo8|qS_)O0hd_s^Hgy%lo~3Y_^|iRf+9>H*{|b+E zO~1Y@xE#f1=sdWd&vL#R?dUK`AEN$};>y->S)Exg?98cIo!KL+Gc^UB`42PXI&-@w z+S6iwXQ1O!lS30(GZwKyP2%I%8{2_qM8>yJm3vF})rX+I5)rx=on42r^Vg^HXysW) zD}U8MI0bUF!dHv3Xrco-l#o{s&PHA%<5;U0G~Fhi--TIF^+`=xg}Z70cP;G@*E-6Z{Dzg>}AdAF>} z(e~#yQla`L4noCDDAsX$fo0=FikWbjNs0WCV~{D&2*T>8igLZJ;dqV-Jc{m z?0mHSXJl9u5tF-^T7wI@q{GJ6y_XXY$&(Cn14`^Ku1SmF`<54Nd9-iBZCjs)K*7Uj zR(77z0DkX474_OTSRspC=?NKO=*5dN*0e~pEK#E~O1`7x>-_|vn#3j;SE4GO{IK4Q z%Qd<_`Gr_RkktpD<_R1RJeT0qW+Q%MO+unE2D=A>Ye(C6k&;>A=&F4iUN~>UARn$0 zH`%#g!GP3zy6R;6HyJl}Tc(BBzSN_D_hHXW(0iyx5>C31-+9b>$(PP_hs438k^O zn73e+aoKK`oHcFv8{H{GU{kH#$p=5NWxMs)j`0sjGyXR)KEg=6f7#BOwK17+5q&fD z7yA0F!7`ByPuK5%a=QLl>PvQV(bW$6_Js_^E=?5HMsQ+T#xyu#j{1%26Oy1&LcDYMLrJE=kSXXkW(nwvP%d8|mr*~<7!k&F&y z1Vu8=Q^wgvGLBKku|+Z_kWn9eo*G#sZ@kajDV?`dy3=EPUZhA~wa-hHhl9=38|m|w z70Ijcd4Esm?VfJ$ZOi*8HM2pt(?B6+X*yop8fUiEoZMe<(udAkcCg0g1#KUgsst;ub`ec#p2Qt~WrL!~Z{^h>m zph#Ya&-+C>Z~t_wt9;&g^75A~R;%Pfj-fc+K>n0mJ0EG*8R>)djxf*b;UPT)8?Lm% z&e&NTw$w$d7n|#ILIsVTGwrPQ?eq)?N1n-B>GM{k^A1Y)Z=Z}#ts`_cX zvPkwvne4O4wxAf#&C@VqZ`1dzpcpTZ+Or>e*3`ia^&Tq|iDB?!1<_DzbUf1;yHq0% z$N6WK${S~wAItjb-ekskuh09}_JugO$LB3Al6SYyyQfIroj&iXB6)xHdA}}__h+AX ze385xecn&V>)IDw%k{9byVWNTN>>?@o`;|Nyv@QqX*#Oar83>e`|J<;ha=xLUG>%s zVJ}Z-XGG(^WJ?s^N1j_Xwk0KXP5O0nyWG+ z|8sxTbui62#Ex_{o?5|qRkZy!+qXsrz9`+(Y`TBv(Tp;SUv}z__tbuvS2M~a7ou!z zTIm&$S9n7axlV=ojscaECz7Y>XhvCT-Lh+>=47mI^>8~S!>blWw%OMETJ%8EOv0kI zzUV+JnvW5%Of{YIQaybvCkxhY>uI`U$FfDp-ogC&QP&%<7U9T$h&nWZR#Nlb0o)%! zpCCH_*R=TnGkJmefCCh1SlM%AI=PCP`JgdbUJYu@e9)LYMLHS!HTDt1N4^2UTCE$w zV8VV)R=@VJer2g>{@8m$lYlj=78``m(<1}Vepo+M_4mqziG0l2`A=$lhozg@Y-D5U z{H}1$%(4QwN@3|DfxFJYMOtX?2V$w&4R_sGYEFJRD#TKA@{qAvSYlJNPAoNs{klT^ zTEFNp(IpK_An3*PpbSAaqTi|J5`PAlJCQ;VxV1&sD(WEha^^eEhYsbU`XTXt0mlYgRJXg75jO-I}JW~YmrL8X0TfYR^7%2_Nk zN;PixHMY0TntS_l=kruknGRqI!O!lJ8TsjCyw8-Ppm5#767c{604N z#^zPpLS$^O`|)aQe#9JDc_1+DLdIy`VDqirexsGj$*I0Q?Ly&QYwsc7UbD3qyM>Lo zZ7-8u6|QsUHsA}-@r5g_a3Qrrz`AZM?QY>`9hfupV zC+uQ3X1WMEQW2SoRd&j8OcK6UL|EisEJl*h?|WA*)IIHccSB65Q=Z)}xMnpZAg{(P zyR6u9U+h;_tbR_P%u z!p#;t{|37}FvndUn4{L4dq!JrSK)2?K+uM#uyTqnw0GpTsa-YjrMW!|W?Z;C$>C^w zLj7jYi5djwnnEVC4|}di-p3v)q{Jy>WP;OW_Ta_d*erUD#!_A=StvEfCLt9An_V?R z-&YN*yV^v7N=6kexhgju!fnJ9yOGe2p5JvOE4RbF_kC?x;0qZXMro z7Kf=AlF;;~-sjBI%|XgT{&*{)1$Mecz@5YuX(~8s_jZ#V11_VG4MA{BGDAJRvEMK{ zw#Q-V9en87^7mwWTN)o{<^iyez!qQafAXP1$uvrr9#J69aw{EY6=%vy4M3pJQP ztc44tKV*c+nY>yHXFLLw*AMh9OyUh8a<~e2#`;k?In=k%6dEno*!mP%AC&&j2RMI9 zOQv-k;4JeRO5@O1s|n{f;shj1`_HUpOk_Fp#8iu1&ws#SBHhnDt+aFjJHi1%Z)}n} z4Z0e`!F*;s7kgLZ4i@#shEYJajTNLzJELIwBy`(@MDH*rygJ+JiEMJ0P<3wI-f+1c z_ck1rZ%n@brWtakROIiv95agyb&ctY_HTN7;R{*~tzM>iq}u3Emm+C&A0zTk;E~{7 zkJRgV>DMFldV2cxaJ`<8emzvL_378KdOallI)YcNkb9+54)iJ8kwULxG$(6HfJ&DM^bL>4%MD%-Vc== z)y`QBHgp?rTL=6yW&cXR6~$DZ*Dz|n_9dr6)7>#$E}k*;Rn z?r8#{;+bgY_MBs~aFvBZ03omYWTB8(1Y%w=(sq8#DFSQ3lf~A8o~;>KmAgphR)HJ* znFIJK`Gs&5+IsI`OyJ`!1|My|ftTJ`@82CRwJJv255de_Y*gJ1Dib$QA~W%r{n0&v2U|#>Yb@)@JBK=21NV!ei`HLv?|uqgwY{oTL~aq* z%n_!*h3}Vn?M=>f=Kj9Y9H?Iv7fN=k06x%8d( zHwQz^p+G+Hd-pJ)^qgTJIID$XI24rXU_O3`VRhB+`1wPp$?~qfU@?yU8)D-|eVe@4 zSC~SgbRWTLN`9M*oM^`_>m$=DX$`OcmtR`1PuF4etC&upON!w>rg(ml!KMkixM#cd z3ElZ#o8cmSp>>N!o7SD*qWt)}@?*Q9g2?laLMjPn=bA3^|=8Q?(;|F6eoW(eoHKi-KJT=Bkmh{lf!JJ!P+9XnWsJ7XnOPTo$Q-GaiF@-8R@vxD!`=(&J}n_F+} z*LOP@xf{M{W^92qh4gTGo!L>#y`Pwdo};s~G` zEyq=A>)+0I2HG;LG zA$Jd=U$SwM2Cb_DJ!16Kc5CGtEM~|Np{lCne96krOl`>q0Rob_mF!lnR;I$PxU0DR zisr0kNh&56xVoDo+^ngjxV!opP(IC2e#)KShw{|R3iA?-JXw`4u}b@Vf2F^;N`qDD z0;}{Tg!J8$oBD;Tw00$x&a+AjzrWH!uF?}!>XH|E_vzHkXVtrp6S@d`!A+Za+A>#S zXwup6lgPcUajN!~$n*wYFWL*T-|RL}*%=$~c+N4-=A=5JzDK2hLFw>J=ha(PAyS1^ z!Jp~;a-M;>kK?K|lPsfD7J$70fZvB$%v(kdzMW@h8A+hMkUG9MHkW4e_i?(f#OA4f z#IH-E_O%99hr?MH{p#?KM_C=XI~#d*u3H`YoAw)dn%ABKT^DZF816J_U2?)*EC{;~ z@~hZkys=o^sJfl88Nf=OPoB37Jjo_&yinHXQ~;a?05jW2`HURQ08xeH1Yrg*zH*;+ z-Q>s8=Dzc~iS3Uu=6IN1(L4az(mF0q)E{!({Y})%Sy~TpiI%b}_wC1&fVzjuIh&_s zd=E{!HrTD_yAE%m4r}#A#T*4pr(!yz6FtkhIeG@oF&UZW?p3`k5A4S*A@SH8we|k) z>9#y_wpClmQD#K4zd(+&hmx>uO34Y_E|&KDi$gI&U*>&7@s5JBQ3yr*E&!R9$)XYG zsvQux8!q|Bg50d&4yIq4!by<}7MBa9XxT{m{Pa<9&eG)2NVwQiXM;j@W`_E-ou5v`-e) zXvep7u4{tG?Jyu4{~9BUiN(?l$fhTs7S|MA@ojSJ+3c`$RE!8wlrt-;0?JjsicmDP zo5~hh3%*NVE&{kn3}P21VmVts0_~x!{^4Scq%|o?=`JMp)O-&vBa8n`9qnyx{}6dt zuZdA1ayjJ^(kxbD(HMK{7%+Z&MTSr;Sl~LY$rioEjge|`AzV_6V3*XgqGcP3rj{2? zomwo_9L0)eOcyH@jGLYm)x@0Dph$6|ogunQ!vLL`5Ui-yovaHM3NU`D=KA`9MDkTA zK(-7;LjhUv~$bLtAb~OlHYI=#PtyD3xxB&abCyDDHXj-;++GQ zKhd{OqU02ECBYbk`nXOVti6QF9i5f@dE#7-m zC0#ZASpT$NC=EMViyEo#^bli?E^b^Ktn7V}5$!^^t!wPJ*}OdIz@dZ>w-(~Pt0hX+ zU^?vyT5$Mhfjj`)ezY{|}BhPHXRtneR_K}w?JbSdP|*+~{FY+^(F0jywil*bRB-tc|+ z@l=0?dI1*73aI{2b<|V+80+izVQ(f}@|Yh&$w+cg2qT{!hnxI)<&J!M9BcCDTTYe|C6AI@j2_38BZmg@8+*ji!3z21Nn}P5emUnso3up9t>k|fzr13k^aH0WfBjf^?f1=>=a+Kz zqA0&S^#D1ZU%r$C`N6o?4CLXXF?c*E83IJzkYOo(yyNjHb%fVtE&V-n3{gvjMAalB zL@UJ7=oX_(`IYkhJj}^6g$3hGbrY{OeV3na96$23f=&J}GvAjQZT?sC zQToew=m#ZUKfu&34bbykiRZa!$M0OK@m-n|FQlBIG@WufDTc~)%CV#v3ezcLNio!= zQ^ezjvUG~H6hqa2!{bh}xc?n}BjWFzDN4%LSFTY?F(ri37h37GzH-)g6g|=vEr;&Q zsX6*Pitg@;4x*?Qp|bBN`t=`-@P|+o4J`73Uf0prXI#)iWVq$Y59}U=W%#KpFi@}{Ppy3TTg#`lh)Jy z$^E|dblh;()yf<>wC^8<(jO>?LK@1GM=>{p|C7GI?)CM5kw;!m47vqeur9<4pL6Ac_&HZDh@VX^{J-PpY<;&cmb+r>w^O(|}cL< zd(PEo0-I=`Z_l~;o}yp89tyhTJR`XR;WIO96L+@?{vhFl&^7w_4*8SOPioCNg4jY|7IqCz4`QoldDI#ilr&f@f5EYSW3kkr>YB{~~j<`L*OF z&1x`m-WB?T(Wq#wojtD*ORtjEY+s$5{*Kqq*cBLDbXclyHvB)7eR-fw)%*TMo0}Z- zHf6Zxc?y}jy4QGduX!q!DWsC|lA$u^Iu0eINlK=ji+S{ZY<3`+c8xT?Ewj3D1_xo77a^g6DsQrDWWF!S1Jb*=TQxHeZ^>u>XIQ`de9;M!<) z&97|BHEEf;_SQUHdxFSY+&7XbM0WA|_R`&ej)Iz{As8-I!SZScrL0~n?s$mkjn z6AmoZsvImM6bV>qlSvJ7-#;@m+fP>w=7Tm*@oPL*+!NP&;2J-7!{^uNTYN@$$b0N~ zvMPz6(5*fhw8dJcb*iwo4|x zLc;lquslP}94f5L`5RhlmyA^uJ~kbs_`8(I+>6Yzp}xgqE+Mm{A{_gsCfo-?WXVZ% z;2Nr?qIkeg*pC#{`*4E|RUDHQ_jMKF%?~uxLgLlwnaw)&S#ih&K0^iJsK z!*TA=_jV=uXjVZT`cK|cpa171_hpE|ZETkehH!*_F)+noSb7{2KaKCQ*r{lX*orn) ziq1kdP&dDClO&ztoJFh=Ep_LS{c?80zl|gi*3(X99g> zy!0|LCzauCVGPG%#&L)e&*2-B)o>n$u<0PKrs67ZS(6HoG9IU>|H)9)&+E&B)z|Bh z&!m1zf8A4k{e!0NriN{hAf#%ih6T0c6g6B55Ate~8fMbNdTO`|KRV!5b(hB|tp!$4 zS1)Nn32InOTs)~vAvK(j3PRr8YWTNCj#ooVs}ZM$g(XoYmAS#l_>HGE?-ey1riYdq zUei#g)bMew)iE{fB87EQnFAa`{tor^>)Mn}YPd#Itx?1J+LTY#aGKU`sT$UrqD)z! zhMlxW=c!?5ZMU=#eq+8iWvaSbLKBZu!$Oi4@<-l`Cq;32G|ng_AXp<{eHr{gL-lyA z-}qF}H|uLso+*4GDTdqT_}o$q;5yvWtZ8`6@~T!VA!NSDJB=Ae5OZAe`KJ7Q*ldAmsHRe)dn%2kSuFIJO4!Q!ri!_$ z*ssTu&1*4dylX1qsdM}}jC(@n{gXxXHM`iq2+^1wC&$C?%;GTQbxBeBaw5X+x>T8&MoppR&tk69vcP|78Ef%PpCnplIw(fxH86cIt!o>qw5O=!}$_gg;V-=nR7cm=K80 zDJ47;s<>dPA5ELfu;i%d{4R4v7rHdtW<&?iSonUGR8V$v-TB|6gF^ShM6tUXmIo1i z3cpK+a&srZ9K1e`=Bxrf%*n#pYh-*y2~ zF8YV2{tpS9MG`nm$b58yxM;bZ8XM$S$`U_2;?-d!T=Wztk>9)u=g~Bp)7PGlsSpV} z{!(Bg?1px*fSDW7xF|awk`&Q)%yZenP=~~s%8pw9Uv?nWv&M@ZZ`qmqm-;F6Az-e( zM}@isoDVzVRj4a!JD_$WrFM(Ou#8#1R(Q>9j@kjqX07%Dm)iG0?G%^VW0~atv-|P3 z{S)Iv?Q8brXr$CG3LR~=mm-&-b}y!Y-y9mAST8G+Z`dYhR%*9HN1?pE(XBR~Toct; z_Nex&Qiqkdx3LTRpVfx9%P6(encDQ&%Y|fOr9;)V@ygrpy(nrQRNnpySC}=N94)lx zS>2cGn!#*(SJQBE915GcK*`FmC-MCv%N&48s?6*vlS)VDBbS-+F!MtZrp)|NmXiOf z?#Y4n*#fO@g|{sY`M^?!ankP6=Hti92*x!SXIIV&Qr~YW!rk^fN|#?b8)sn0TKx72 zOum^fh(|VYz44pNUQ!y6!3W21?OF4p5UyoLFsEuMEyqJ^XNBAYMX9pAY5UjK z6?$$GgO#4wq*uC&p0QTQj!Mg>w(!;R^Jn8bq?SDouH0J<_BkqN#bVF7X3xWWU1}%(m)frOLsf5-kGIE)&z$u-gx@0TJh12C zy<Q*wR9cFds_I>JhsG@WQ)d*isE{(Vy*=k&6IteIY$cVM zOC)pkJj~-Vlk>2Y0IBG7k#_7Z(GfE-5AO-Ix)YvEi;*&@wP#Z8kN% z65wUT=X+Hre||n}Tyt#@r^sksd}v&OuyGBQBa7m=N$^+8@1)Ip9OH%xpEj<7%Q!rW z>T4$RR~a`-mizxNM|H9y5oap=3d|zrLUv_Zw|TZ{IVH)p zX{}tQF;;H~kTPvAz4Je;d#c^Xe5*1_BDIK%8b!~G_2@cy419ZIMh$%`|c{^z{DQ((f zd!T0IWVa)Fxg5b6`HBcoj`&&@k^hP@W@IKrH#{RtJ}<6VXD`c>a!ctMogR+zd}Zi< zReIKF#aV7TNq#Bg=IQ7&%J+ngTc+?wbH$+}%K#rKGZa0tGHwSdFkb;Ar+33_<5)Rh z+-Fjrm2u}8t-D1z(CRipDxfRM7B;Ra0*Yn7m>uUOxx~0c)atc{DmULlZRk^pF7}(l zhKD26Ru)WI8qO-5$Juz$h#rDtevF7IBPvU2(y0npilST^3>fj7gije!>c5PLS{l&U zj~^i>bYOEt(P!l^dKz08A8kSbWkP>C-EV#hAKFRwFR1t#Nmf#s(A!?!-WDA5S17AY zh!b{b5=yuMRrP$Epv-)2o~F2s zeI1Nx4fUM!zUIhu>S}ilOKc_K<7tv{%Eud}k-W<+h}AU|Q|fJG8KaNKiE!gb_|-1l z$5o|kt$dt1RQZ+Ft*0wx%INt3f3H-Sd2N4JQ3j314ng@lxA19yFSkw6+vTrhGAVO@ z=Sq0DypKv5RJS(6#oI5DkLIjIfx`AL||dC(J|uV@-J>DTo4?eKY=o;NA@{H&%) z!si37Vm@2bGwz%8O2&G3N#_9KzE+vl+jf3!EILqr!mD=N=ZU^L?%&(qMBMYhqgzF= ziu>PsLwfgl=3cOI=dR08@#uED+O3uMDjQvqvv%BH8^pMqO2<2FQ<)&I$a@ORA5o)K zZsq`)GtEk)O|?5+yrRHY!lh%!|4~P^@?yuiYKZ7~#_m2%rQ>IuYC1Q6e~vm1QO1m( zqjkK5w++CL4ICW{xpk}@q2m|{i1OnKy+i)L{OIVIQ|TDAGjoU%9YpYTwfas`476L9 zwu<5%IMk_D3!tBS;?%TNgbPnft||3$|Cf5PCe9!n!edc8Ww(R}(T^YpE6{~lmpE}A z!;Hbid4c_g-^{AB_IXg1(wWK`(nUO|PJaK;8Q&A%KZpQuws3}Q;oQS#&X6Z`E5jMm zLC?A*d~T#^*b%(%YIpi+9L|tgn96!3dR^-eXG!+u75&YgaHh(>tWs9=45@3o4KoCP z=fL-#2ve>*EKAm13Vl>%jK{gCyhX}*fi7p_zm7cz9ArF)zE5vIN)F_$@Ga!VUC>TA zAH)Cf7`PmaomBiE+p2dJe!~Yt?XGahKym&1YN7CJ7t>849R|ATD_O2o<8;*Jrasc| z$bvms$r@nKl#4jHg|786R&EMDOP6Xl4R*OH9&Q>f!jzjn(Oc91YXSfQr{M_nbq zc?PQL%q)*wf{zz)0{G3%u524Id1+H7sp6EgwtHB+V?Vk!{-9lyeKG)NIO;3D&Ok}CbzCeG^%066Ie^&Nao>G`e_kjERAU7AIQr3q-AUKHm! zns}T7EUVL$VW}vT>Q-xCUFjK?WLH=Q>M(Z0_d8u-*`{$AmW%0<$f4s(2=q6VRR|@tmL-^u&c40?O!MtwC7$ z^Ig#cpVSJ8=Y3rh1cAjWk_ACAL*~~05|r<_+~LtKzA0x@UuP8w;Q0X*y&rkidG=}i z*J}{Dt?Jn`J+Pnm*1s2+nAkX;jkDjV+)ogu-;jUGs(;$t#K>=SRkCycjaR9S!B1og zf+yGNCWW)}M~?RmuQ_f^k+|V#3eLkl7va8+@u~8nsa<>l?R}W;A@g6rUxXQ-L(z-4 zN7pevC4|4u7a+2~^^KGay!@=mjTC=8AJ|L{nX{k71-!0tcv8y5t@!oIm>Y5F(+M0()hI1jQ=^=c+JoO_Bwpca7f2lP2>u~jyhdwJ57#d? z>QPb^n}*AR^*!kt8b8woz&fs+yp`W(B!12+8c3Xz1^*ChJtR>xLt(vh52=cMg3E$+ zn{*A0xf*MR!aC1yGZK?V;h#X_g^u`#Sc5edT?f6cb|O`=%=kyJ+H>5{Xr-|lE3Ae> zm3T?%wV{i~;)5&H3yUJLwsjS(Be*PBWjStW++lLT#_KA{atT%9QZDU*#M4BkUdJGb zSS1zKh0cO?%hszU#|@2D8tX%aRZFN6t8lUh5)UIq1#7y-I?Nebzt|6w&&7VjWzj2< z=tRLP zc1vSj!&SUvH5ocp{D&098sL)PWRRwzaS*ebzS_lqGmK&UHY4#PY(V%7yX%>Gd~|ZV zhyA-vJH=B1zERXGRJI6a5`O>IIhomxdUhdXmY|Aw`9;V~!>w~vk^+D76>@kjtP4q*8mjH1G?v667Pxtyoq4FxIwy?j?T-nDo}Y_%uBYI zM*kt^0J2HMw6w(}X)&vDC1kE6Y{2Yli490|dTxcM!g8iZCH4Uay5lr6DZ*O)>tS9%5zx zJw0YDqRgMxBjm^dzJWWz$sNBh%~q_bQfy<$+#>GSdU2bb%JQ!~pWV4j*W^ygos+vr zF84%A{xuHM;vh0NV|JM}oSyjiQ~v9}D(kENS6OSD`fu^yZcXuW0Q{TO)c@PKVpeFh-n(a2}sDCM5{B5 zMQYcg=nj$YE1T}9&<$spK&O^JMfV-)UIU%=&2{{BT}Qnm{C*6-Z&S;y_D}r255AWd zjo`Ipbv{8Q4w*}pt~XWRr?793wk~P?#wlJ1_}cTxCIos*(Jw;`9NTV@KAT{ZwvH$r zRD?ZM@1lVJCE<@h$Y!@c5dvl*0{eX>xhxQWf#ihk>^o%m7z|btUThY&GHx)wpM&q~ zC$>d1J-iw=1O<8n!f$r%!+(4{cMO>w;JGlDL9QO)3Yp6ur&xKAU&3=QFEzy_s5FNs zEUYu@X#xUR3FzY(q<}ffzSiwAH}ZXCH>l^*{cb&T^ZUyu@%`X$-QVZs_lNoYQy#kt z^7{?^ep3xMeldQ(2;al92hqObRY3Tw?f(|0qLvefvZQ)RsLb4;O7(98eevP+#49j3 z?1}QE>`Y3&SdX)}87l2wyoY-ulbrMZZx|Q`&m62lmQn(4)aofJq~H%)V^!cAT>M4} zd?y{9uNitCt0#2hOWsueXAagO`x*SwB&A|{oLeCGt3CLt$Ng50B3_a8$g_ex=zBq< z>}i8lKV)vQ{g2)#F4%ySlVhN_tccgo{mwT6wZI#J_QOCaYDK^u)-Fr18Tp%uB;(xU zVq8o72qXlx+S0g#_)Zzu4SHA;3%M1|5^P2GtYC*YuPk#OIsJRB8XkXS38s`k8Q--~fS$-a<@I0t+4keSUk z4x6O7;FF}>L&^yBy9BP+qi*et;2`o(7fD8ENW#SM1TIo>EJ6M-A)@rMx{NtPnYwlkPyDsXGD?G2fgp`A=JoP5OvN0IW%v1stS1a9&p zZsoEDCz1bC@FM|NBJJe;U#=PV4!%=?n~42`^_%H-P1axr*@uul!nK%9y}`=Bz3K5s z*5GvVB#KD05opwmJBf7-_r;)|7>6^+xZn&@=8J(I9XS2Quf^Tm`eh5gL4KSw=l>^PEMYl5F}g{fs28&d&D_aHL|m1Vtx&;SG)?hQ@E6 z3#Zft7UQa1X&flE?j$GRLTwL6ImJ-{7y5XV>MTkn^T_8957b#%!jkLZLQC$*9T^Q} zf1aF#3-wek>P4@T%0=|KMqAECha*|$W^y}RXwDVDxlm75lH_i+k7QMs)X@9zsN{_9)<4-P7D8GYhNCBhQtT2GivR>i&-Cr zA{|*DM(1@$IzD)lJjKZ4H`{WyOhdraOQApD)V4T5A8MoX zE@m(bDeJ~Y=lW0Gdq$ue6#Ho#9nYM^ z1#^+ISZwq=NIB}>JOVurc`ke_x*rFP(tWC+-|C=s&qefnqzsZWdc{i7p0RRybvMc5 zSLkIN-75+D+ctV`q8B7(uh{61>U^ITfnJzARTcV!PQLHKi8t!Mjh=_-_meUUDWi42 zr-SlLl?e1=-}? zMxo~x^a(b4KBAW+x~eplZ{+jc)~ zOC{x;7~pVZ#GXhVTo0KQz#m=>iUqq8p`*w$rlTq~Re_cr@|MeaKt|+x$2>Nsn`Uq0CkAWUNKXeYAZS9U+@!)tOG%<&Y-2z{Ec zha;6kD?MAAg{qy*jjW5q{6`LHjz2Kdbq)nnkwcl|-BuS5&ZH)jcg31)uj|RS0xaRl zRy;V1EFHjt6dLACwyWquLuMZsDqEZ4OrhDNtPm4CGcCbP?hpY!mn?tn6!0Hg*fV*y zfM@l9&m-k-P)2WU=5R&<{I6_Y&EF);JOw@kG^$M074T)P+?u~l%I9K&FMt~fJ}&}% zK3N(n@Ufs#;K$L8hRjqC_ySVqi2)v?2Jw(8WPZ@n9kmj{X1EV}ro$Ri7LJX63wg>}**F4y9eIA)F8Of8S+yn!`t=ky`g&4+Mal@>?>Z~n zfIpnr3Bm0|7$vfdQp&5IS((%E>RHdMJQALjev&wo?*(Cycd3@*WO6R#=SWrddqHD8 zdym_v3BkkEYh-8eqND>mgZx+bmmBP2D9iq=PY0nN0L9r+NSOc z%Q?zOPJoP4jolXxa+HzGGmRB=l>_x2M;UUavC(tkQ*{An8os@3({^NX=S0b1zM-(T z_1Dq!4W4El;A|eA+3lf{!2;wdNFKjA7&NL@tj0M5`mAO;8l{+|g-CgMYfSVbm_0-< z5P@EVJZs70H&=m1p?4GXT}?H5X`&Y;<;>XVrVf z`oD2r-OG{ZU4=dsGzz_upnuv#d!`)GE08ihHu{Vtg+4z5y%Kqn75dYlQRt`8vf@6P zjb5JURY+MdHhLk<4(gs1fnJR~XEuvxt~og~LC~++H&`nWy#^`Qk}}#eKkJPAIYc1) z&R5Cc1LT>k&^J2hWdwb$jb4%HwMp4M26~M3B{LX8=5NXF8B;mfPA zjjYbB5053w6xBUk8;;bf{SVx0HM--rp>nVVaW`*@RTlr@Bt}`h2$pa`uN-VemKk6{ z(i{biDvMRI;Ru=ULTy>JE7R;$Qa%|Id^MCI_>2hfHe{)(z-NI*fgeCm9Wonxz}t~B zTMY0RH8%^i!SlLF?#!+d>`sJjK^kJ*LDv;obAM&G#>d5srOKze6MEC}snMemNSu1u zo+GKbzPWVvxBt35S0&hw0y|M)bdtRQVNBr{Zo30iB{+aQ38JL=2x!y<38H5YnKfaM zc)JSh3qC{2>l%MbOhd=)*|aAO`wfC&=DL?g>&g_#zQ*Y@hh9SDgW-UXKM1gRR#Aj?2e#jFMzmBTr( zX~6q(ptgjpDnsTcWs{iTiPQ_=10%o#WXY|-3xh_1ufUcT&kK3LXOi;V`e@B#Ob}Ic zMkTr@NVVXbMEC#*@M$`_gUAWeOF9NlknImaTW21uo#5RZR2}(2VE>BhZ(T zXB~O`=06Q>^hX4J_d{;<<)nNi26~K4RjpoW@Q2f*MsPI|+K4P;yYi}MtMHlQ)s>i$ z@T$(#g&e6?uL2wpzEFfC)#~MH;J%QFBh~7a^FS3+Pzi`!qN-q8Ms-!e*y`2Bgbm9m z$B}CF?xTK=R=1UKwt7!9)<691j$8HMFtL8puJ?}j=UH5lq2NSP%jc>2Q%ylMpaPh>f;R>0eXMu86!@Y4-6cuj(zCgoyK zM$dd%51{!07#j|4_23z@3{&8f;0*4#C%6_qyeGvOK21_ku=&|ARI=WDc~!>k#}ZDIbUl{sEI2;EzRs|4Ek6m!kPN z&?xZv0-oCje~{pRk@7GoqXSx(OFF0&lur6Gy>lS{FBUKkJdSv{dWS}k> ze|RpORTq+Qp?z&PR1=Oel2dTulxI0PsFoAn)?UH6;aL72M;UTkyEto!b0N1XNlyvi{$Z}FM&pN zImOT!<9!(q>Ktjn97!Z)r`YI=5M83b5P|+Mc@h-*c+lwn51k3YdS@(Jg`k^{n_lJnyjFj_YqnFgH>gGSZo@qgzCl&f_2R)0R zr`za>L~lvT2C>oq)Sl@Rf!>-tSrz(z$1{u2#D&a)HhLqXr;+mHXE8lf6$wnw7!l}g z$+MI^e)C??D8IK5^tH9MXC5Ycds4m_8+|)+n&?ZedOg#TJgpS^LeMDm3)n>Bd1)Ix ziRhh4nGhR&l#Xi42=uPxxwJ}j@9g;9FX*@J2XvE({s<|zkTN>o8*226SG>A+C(jIp zUeH0WD(LUp=#7c~I4Pfujo!J2@=PECy$5+}DD;}3QJ&e~lAcMn(VGyx7b&yGMt>KT zfqt(Zf!>Ea2Um(`#(+kl4-xb;59p{iC3;^{E+u8OXDaHbe*3%EGyTakT%j9IRPzb? zWE;I1(Fc&SRc!Q*C`{CSSOoersu_Vk zh&*e^<2Q$ZMxl2V^qn=eXIc<_2q|a8K#%T#QGZP!=)WAB9TQ*vu6Qz+89Wl70~I^f zpZEZV@^{6D)I>@C7Z%D-3Ho4^8Zh#cIAHGO=Byo}jeZM%S28_ka$sbu;8^OC8M@G6 z2lL~vvLBO;Kr1TxA}{{3B5J+Iy;}aV;{~+mau0e!4R?dyI+#JekHH7^b0SG1AMd;+ zYaX^ez7#Br*2PPt++lUZsd{)_XdRqEn10dX;ovnyK)dnEW%u&aI`}GCYKdfXHfU5Y za}ayTkl7SkifyfF+iRq}HwJigyCF8tukKbZEjXY2J3kQ{->e?pY)rv-(rozl(8g@A zG2G~;1s9Ti8rh>~M{BS$9G{6_?BlYu;9~N05s_wj(5MXi3&)`$vp>`m1FWgO-xLmq$pxsLn7cN}H#@kd{tT8Pr53vQRU4PK@j zvV9aY1z$mcnSwQbbw{>s@CtbjE$5f!v!GEaI27F?o`0{R!_v4 z;)a8#yF#A?8ijrf%{cCV*yx>zo|%+2W21M_%kHBQ==YH4_A=4EnzQV_E$BII^v*=j zO3Fi|jE?GABs)Fx?|HB8@#J||p>G0>(!G(Oe_BaoF6o@`$J`>Ys341dRP84w!4e zY>mM+*P`A%Sd6+ZTYybcY24Z+E~EgZ)#o?!i)|T@TvGf*)Oz`B#;N7eDIrn@JVu)2%2`)vy7< z@5m}>pNb0Q2-}w`RIKIxtzt^XdclAVOSn<>oAtOL`F$7A)uI2lK^~_a^$C(7b{IQx zUAw(GTD0_PsHW-Y!0Gnt6<4dnDDrBW?0d_EtlB1RGQG;>Eb?H@8DiX@hoJ>!k$Qt7VU1QhbVUN6xp~oW=*=5d!N5v!Qs>>WfrhwT4Al9$+cC<%&2Rl;o>_zm5 zkrBPy`N!GjzACvc~=VKBIA=w2aXSR`HV} z$pPp=fXyG!@7^3mo>Q0|uc*uBHOypbbMX7>^+JpMFRNqPn=$P}?7qN`m{!R9L8Tc} z&fUGTP=-S0lOEo_+Bdq`TkhvSam;OzRdYU+|04Ktz zkhvUmVTt{N!%5i>lu)__?1fYa=!_*KWRA2k`_oY)NcoWHX8gjFHkHv&(@5=ScP)#n3ZpufuKDX}CyCwYUxkjFn^xm`?-5s-q>dIJ?SN z|KJ!({^>p1jIF}lQk+P9t+$#&{ev&?dQh$>6_V+e;G3Ch&cN_3knH$1Q#uagvA=IRSMw)sxFxRUcC? zHt-*^(ge}7p!E;VAn3&f1daIJYelRH_+@JNhx2y1P}%vgG&o!N#)OoR`7P9z%$F>k zMbNnd8c`~YQ&?6~0=~`bWrj{bB6?5i`x!7~6QvCzDw(OYm}Rm_ueUkIwT5_w&0^-qp|6UMU_cxPyZ4lWjTK@VhA4 zhi}IE)rz}z-1t&EqNdCwiEaaYVst?~h<%Nauo~6Wcgo~^-0WVA`n`aB5}yu2q6R;u zpvEF7*5YX#<$g+41NK)kRr0a#2~U-K*w?vN{L*DG9ah7IGF42BFjao!<}YA=2@oqg zvn_gk8xmYcZ9bn*voTc;6?50KA;I;$I#;gR^P?SaA=C=%XxUv!S6#7mSCWFEN5{5B zp+{a@$7GD4V<}a+76QcThifr)+)OQULkmnf-uS*FU$v5O&i621f}4O59JiJv z0rMd1U{xlQR2csbyx|CSf5_RSSd&Qli^qt*R zjt>69ixn08L2UoElS;r+andI)CqeYP81h}x?ZioIp@{W4JSSe z#Bf5FB6thW&NRG)({Hvy$&r^IV}7=zc{x)3tqS2ivX~ziv*I}{xIiY*| zcFXBq2(b^=`RZzZb8W=F9#49bH;eEZA2DL8RIaVBv*ZfbB|VjpC8xRjp)W7uwxn-i zS!BWtL`Sk@4o1k5jk1!NBY|N3jBB<(_kDv|Knh zr5|31j@r)6nT6En1Zx{_97rC8Ehs_IujkS{dTc32v1t^`7gvPS3ApFse)jhCmWt&sEQ{Re=0Io8 zSnA&NHn-mH-gHl4ge(XTNjNuRgm4}O6)NKbfLQsMC(*s>s9+81v*C4~H=KuE;Tb$C z_y8}xk4uQsR(J-J1kqkufGhcDpp{UMVj9;b<@2C~swJ63O8p~Mpnf@g*BN1=`n>0X zVRH;GqI&q6!FyJ`t#)0mK>?!zi38>vV74A(&^b-P&9X8oScjr~O4MpOIgpc>F-RW~ z^#BtZVUQN zNk}Ghk}!|Oo4X=2LgkbcIrB|sfPc5ufEATWs26!Dr!*nXjXAjDO;#y$c;}7|e0q*> zt*f;u)vp@oG})SUU?KNor3H2k{8xb=60F^q-Bo>buq`Fcpd_5%&>u|rW>UfLR=kt` z&*I$$)66N}vhG24J1zyeA`Lnrbz3>cTe`s^bz2s+5u<`nP}8%s>65zYcoB2BZiBK` zsHIGKF4IZYgTKl9oP2?iql3N3_OY-<>>lunt#-98BckPtAW!AxF?EomcyAf}fS6*F zIXc*f?9XYbuIUYdcrOm5we!BM1`dzv$n3oj+9z+-G`F#$`F#brjIU%6Tsw$d8*%GA zE;yJ9Tz-uKG8^TiqMN`m9mg){GjNYkCaq8oCFNG3jM;v71CO4_d$Hn69cs#U*QrCk zIv9Fd+ossySaqS9%(4eD!i3I6rhqvWAeP^ywce@b+E|y0kEJ@bMIE$h9rLQWmV$i{ z=e{O-kwm$KNbma4qlL_>FwFJ^P+bfY$?)SW$=8>0c%ltD3lB=UIDs8hxLhRe!B95) zP2g#ZaTG)9U<5-xA#uQ5LicaMwN$^|Q_Edht>a{hd`5}Pkyn-n6wr0}l;W3nk=mUh zUqYIIUQykTkd#-iZ_+?76R4B|+AY&xN?lL8)Ez}(w{^$K$PNsp)RjlrtyOT6=w6sf z5HLO@alkCiQkRwa$$s-P{92FBf0d%Xe3f7CwO+m+7l*{c(WuH6p?HlHb4bBmHD3L1 zzrG4pL{a9N^j#J%BMTTh)y?MG*nsHs$@_?)8>5&x6wQKq=Rf89*GlWTxlS zi7M<1$X>)2jY(yTMh!ZV8*4EpCDB$Cgr$BXH@kfK-5{tHwrWufB^T~95%0zDo#evp{E`cIRAa#V zr`9bAi_Qf+QXd!GLD9=+if6{c5sv0Z;T*SPe}cyJ%61qpUJ>?PWPg_I(V81FfqbhM z5!D!kIw~6rykZm0n=Cr`J6bs*Mb@5NJe;=^DVeH$N9^26wbMCWs(r-5=t`ufTD2;+ zYQlbm?BC9aRxM;+WW;S*`1wj)@DzzZATjPUxMjV9-oY*F7-Y~5n-FDjgRuWh_P#M> z0j?b2?4)ggbr-&Vc=Rb-EjTx-+~opbG=vE>;{ej=AwbNYkM?udAavxPke*>6mbsrlL*VQ23J z8k}8#E1N4@3TV(f@Th>|SI2R|0t8)1P`qy(AgV$f&n*y@nWZj>L(qqMePu(mCPWEB z^aMo6oCd3$Xr=LD1zv2T@GqhD)$ZMy0Qd4JBsV)UxR*yEseUsP6NPWplwJNA)H-V) z940n{MoDN^xtYziQG`~a(0zUyWd`95*|cJ3eg+1L=|WY7 zR7-^_x-W$TKh6%H@&Gc2G$itp*(B`$JRsEw(nmmyGC2Ojt}T#RoL3yqvriOc*LE34 z49@(|u0AJNx#U!vt*$fxqFHr<<`mGwJR&{88wXM8iX9Z^m$3nQ^3|wGP&E_RL3C~P zlbtldk|IdycxvWoGa%~jDyHLxT)RGZJ&u%aDsc4*_?PEHu=i)P|#5F(n!Dj#N zl=@AapteL3GN?80(?JynJVNLrQ|W-{j1HNX=o4iEd(C;9H3aUWp8^<;V$%uPFBzh_gQ6RfiDQ8DCzBfK9W z%Q^ZYF#e;~Zwu&}$fP`$jgwJUX|t1bnY&enx|~uQ&Y)9@VnT%VewsoyzpVZ3YOL`0 zf#G6DqXl%wa1zf3G2Agn#6Tyr7Rn*s^9*W%70MB$d|FXX%t{;Hyi7h<~1-7pD+ZO2it{M3o5RJ!r-v zftyvx2z8oMEFQovx7|jV>9$`yT92iGX%yg%1^j?exYB4b{WgWvkAWI~OE>5ZrqLmI z5WoKbz4%Qir;_pkQQUY9i34wpoh#nhfT`{A#(LIMhF90VyY4j1@ z@j8jqKn!>EyT?wBGLlA5fLh!kly8u-w4!{-q1 zP`*XV{fg4cVoRToe8S&Ffdj(Q-zMcEMLE~O9FF=OGFN*j-y!7~MXBCL!E`?k7vlZw z9?JQoY_BLAJD6(_zmVD6L-{T#%Y!mxw#NmPQ}*Uiyt9B51}G4^PdIhdh9CJ^C4XS##i3S&zQM2HiKVa#jg2+G1SXE6M#8xN)@PK2pNk z)UsmjGU>Rh(6kKh5bTjhdb9x9Ek1|U2RF@dx)(CvM>d7C=L=%?r$*ibIe04*n>2ks zindKWn8@WN?7?andOTPa32L2!8zg8YFoFl;$rLbOWhYphiQqln&9(7U1}{iWei%>R z7*n`&QKI``!bzSqW?j{N3(iYxVJLk|E3_KcKwIQP7(t{-;(%EW%+_XHv(HPFsLd2L zR79B#(U`zx*77x^lDk4$p{=A!1=U@hD|c~rTZ4sF$60LohOBug!0XjocRLltJe(EB zCiiPJ?}%r}{3nw;OuGoUX}9;j({nDz`Ah0{!GpR4~WfJ31SFHGU)@KNLtjEw#_; zFLxV`^5e7o7_rKsiHKZGx&OfS$Vj{sr+jW!=8CG8)A0UdKGKQH=@gGeIVrv}#7ER4 z{Y3mtFgY`7ACsdH8E(BG0myfo$-(Pru0QBsaolye-+)*)gBJe0*q*+Ee@aWG3_zlZmqc_@pMvVx*4 z>`=Ze((8LDOOWyo?xiC6es`qzMRY@EE)Qh_DZf*cm;bSCKZMQ-{T*b4Z7)g64;AHZ zU?_iPNaOL9hq4qY$ANO~eQ{i?A4ed)Yqhw&G|3(T8B!uM8#`5lTi9#$M&@mJ@3;a( zDHIRFVCw?hAcdj=Mko}ok~m;y2eXysrFrFd3zz{Yqn&Qy1BUVAOqEyvYSCRa^g202`f>5Vm3%iFpYT>A8Z0AiJ7zJ)`f&VWR8Q;Ob&8@H$uuc0MiQr(rQF+``?G-2K2EwaW8e=w0Hds{E-NEO1+EUB=%{y5$a68Zq-yBX6`Z z_0Qgrza-{2^Zlz9Z5?#<{~n00gxLQ)Z8e@p7o)vi4CyOge~1UAVXs%k(Bt(F0B?0g z)Wqv^F+!lTkttvvLt|$xXG9~t{v89}lcGC`XtNH~rPl*1sEPKvQ1vENHKDqT*Uc+8 zu~Eb02irWEUFxRWRecF_9{-DUHGH+^Zwh5!vlu0fZaxQf!sTxed6(mVpq=i}X8(sJ zb-jo3c~Xv7l)W8F3-Jq?vpkd}xNYPUs zNTIV^bb6f>?L;Ri+mh!qD$84DG{Z^c?pmADGWsTnCDxFS1RuI#2@&ph$(@(n-uch= zKOOcfC~o1JVY|jZt%Hpp4xg-Y0_9d@A))v*W90m(bvdeFVWNC2y)$oGO7Fb-FZX;| zLM%RLO)cEgF@I9w0yWoKp;k2GWEd##`FF``Gt9xtjH=czH9@lXF?GY*^0-zYD} z@m5YuBlhFhJx1-N25$|G_DIP5;!l^l2yk5RD2bl~F$5N*iK_b4Mx~XTI%CO(z1ZT%8tar$oBCN4e(R}AJ&!Tx+!7a1oa$|r< zatHty%L~~65HbI0KM1t_bFl}ID*6{bgsW(sa~Mh$eTSw`g_FhfnHa(J9VABIj(@C^ zxCYhLVW>#XLdk*W=xVb#G7CzIe(%ErVf_qJ^#@gieyD_nZ}3S<9ue<{JUNu==i$vp z-pV4uD5{F+7gHt4KM@A?>n~XPB^A|4z7QS@C;4Hy-Js7jMD2Kj9vR3e$(hDNP()@H z4>-DScjXrFf-iOcF)X(_6kFRAo)-7eUOm@%^#d+aMnz}5ojT`xms z-``x)QAqGhRuUHnF+5lI64j^YK8Cd+vpT57$8vJ5GA zDatb!ZOrenB;vjoObTO`CFKG|`Klv*&|jon>7gt~$`PQ%^G~?oq`RnAo);g%MffZ; zRsx-#*|5Wu>G=efZ`br}%hlXj6b4*Jj-G`FBuBergdD9xj)1uh@K!yhif4KPH!fI{ zLeD-ULcb6zIX&Nk?s|GAy{V$pPV_yc>Y=dKBI`0?jX6E!duy4V=s*|3J7K>) zNPwpR5Tltg;;@ow4-CXsKqlzd+>1GFPT4OolnMImMHqh`o)hDrzzD{_PU3)BgB$CH zaE#N1;=Cg+m_*r^o|Xxki0I=80ErzkGkG*@Osa1{6{R5(?ar@EA0DDLg+yujw!(v9 z`;~2s4 z>)bg7%$I0*V>rbz9Bp}Aunk51IY120f#uLPJl>;FJ5uchRV>5bxxm>#!~L?J;+%Nb zuWrL1CHG8l!|-M9Nlbq zhF9HMD#R!T1F^L1_YA{=m;F`0M!NV1C!I>15U5Pp&wsB3^%$m=~ zTC!RF=BSX2fR=V;RH_R9tK{F+Pv=Xn@ODu@W?~lqMK`5;WRJ5QUJ3haHo2#RJJypV zFtj9fSH_=1dng6IDh#3Vx{WT5VYtAb!c?=eJf%Hw5F>ctAMPCj<_AEqy5gE`hC0Tp zL^sT*B3VQc<0G`uT4*oqRmI~6Q0iSC-;AMn{20>3dJXOqkMF_=@)nXfV3y&o|2(ca z9v4vyC~96`XJ`M#S(>jm)I#w-DMo+-9$12yq_C6b;(>!E`OU{Heu-UvYR13>YtGvu zLB&M)KP3NyG_i!{=inx*#g0DT4+ew)LO4z+c632Jn390R8 z!ROkB;dZN2+cTYU*Y;X+Ag(h=3djM1)~4=iqkon63V7pwuXUXtz1?T5oAV@nYd!Tp zr828LJ@+GVPxdB)x7~#D@BGZ#ep&7hoAD^9JQZ*?u(#n|*7jdK=AS0wG(n75F3<Z>S`|)m(z3~3*%BQ6sj<$y`t=ST(s0nps@Z<*41E*_L75sZ>Zkl~NcKQGEv% zc8l+6c2cQfW~7n<(hGT_ZGn1+e$rbpJn3NWL)D7NgxbK(iOsYeV2Lgx3U zT;f|%Ja4^Rm<4LcYlx0i$My#LdCBD9Z}`s1zL~ z7M^y^+c=N831r+Rj1g`!da$Ic4(3Tzf3fxq7OAkcb-u$;tnJR&Hb&AWuSB#=~2VycZr5 ze-4#A^EDhJ^Y)r|?~#r@zddhzopjGz{@lsy>GA}fEuiK*$Olf*L{RBz+<_k>w-2Pb zcQuht!Fjlk(USA1Hj!EZDJnya94B4VI0%g*rt!0gA*XRCkG*vXc(Z#91wv-tA6(*l zQG7C~cY_+PobEJ3voJSM{~%vtAe2o=`JSRIg-EH6AU9GPzi0PQHYMdqMOgz#it^m| zq@3!ZY(~m7MOp0x-Nyo)1Ez+|Cp?tRNm*J^o^|@LH&J=<{HKSq1u1VnD)D}wr8wXl z^PI%{A@JG#i2TxEBHC*^;)9N>&k5Ed98^2e7SmG*xfqZ-yu&~d6<$o&?#Erb!x_;5 z`wH%7z!rKGP9=H@(Y-Ya&%wYYjwZtxt}di43R;A#&i7P^rSMM}hTlDcTEZoi-AMVz zBSLwfL;0!%A&ZCd5mN3@l&6o`m?8KBbsrXmF&`!6d__6)dz`uzzpv3P$ zaKTA=QSC8a?23ypqL7nG#nCk4@4tFro*-paP{O%KP(XAc>WE#H6rwlTQijW}A44fb z*^zbDhDUWF`WKNv*&RsYfLQ>{RvyVDeM4*nJ=>q6wsaFw&xA$ILs3xc8LNX9h2K|x zilK)v6wf`V>u#f07Z2bQDy=&6s_tjGeM=#?NoIT(q~9o zg`}+Lkw1dKLo#f0JCWDkfC<}kWc#ZtQz~*Hz}^W>Zp6k4IkW;3Sv~Qsj`6UaIEiEk z2Y)Cr-vegkT~frR0ge)MY^tM=5{J$B*W<94FcgP9hd5g$AJMVti4h#ui^RCE#RViC z*Bpn9WNgM#bUBLl8~a(p)q34&^WxhNTw=Q%PJp)XSC$}SXYj+PR?%lZ|K23BhoAfXyZD!)*1gX`U|${nP=*5}|7 z0V(+Py;Oc-ok-SpWR)O=f8fG{s>raJM-M}B|5m&2PCDw2&C7%`1S;auC*xgov)W(R zu;CDYb=0}6{nZr1u)p@9L|EhDZ1LA7jNq@5Dxp^a!8*)9c>MJ|gY+tO7~h%xGCCY) zao`d24a_}##QeiVV50h6KH_qsu)apt=E557M1TxCqK=sHkPEKE1tBvDAmQAcEA|5* z(s8ITN4}#jTvtAa3uUXD#lyUS%sVL4$-G5R3r3e|Z5L#cERvC`G;q-Rn!Rq1+=IAF$s z+4AF>(+-QMEfn<-M5X!L#HTj&4S<)2H%M(*C*@mwsEL<1oX0nqkZZ7nr};0 z?@<0J5|;!qk}osFsYI!PxfL=W0JXph<*%gtyPZ%beQT%GC&+}58SkOINXosSgb5?K zB&f)KgLE}?IT=R2q(T{4a=?7+O0IoSRMErQqXoxBTQF?~7IG|@p zxqW(uY{NHznTzg4&yd&fQD(?0(5P@^CCs5VOrwYy((jsghD^Z$c&r)HXem|GGvsZC z*d*pl#EdaR9)@UVhIBxoiPNh$& zBoNTD1RV!ZeLpS@6tNso z9EDB&5GS#BAV#n^D~WNw17>R-t~t|HB)6dCXCN6W?m?wdD&qMj*dEreC8?T4>xV@C z8xdED{4wOo`A$<0Z)@`2D-w)WDwq2_Be{GDE^+1Z90o?`@_1Ydw*~4xhdu!pwNnZD zc`L?8o{$-j1Lx>m-e=YSz?DlMGMBoMb2K@lT>a24S##9`VEds#L?*wDm@)E`Joa@b zU_}9pECEe+yQCka^u8qix20tAB6P4ivLB-9kjP%}M)tTJ**x&FH62cr$Y#L^kzKDM zI}ps)DO__RE28>S)T>HV@167%k0Mgo?5R^(J_$#2Zo_P6NfFioWbFdhC?A=hZnu|4 z3H2l3l{68)XUSJw_@X9&u^Q{HHrJ1ZM9kfS!@+POm;DSwN#s>D_Z|3D%>6)_JBP#p zvkljztGMP&T#@}8Wxt;yiCjzO8lEJ<`u!zL4{JD>RAWIEtCHmpYk1lY$Q882E)7p( zC>kEaT(SOvsiNU7j1Z8mB*uMU2BdA2hC?YkPH8wECfOZ^>CtdFsgAdZtzji<81VIZ zO6E`g-Jbc=89li@f07ZV@cbDjhuEiJ2TnD`TO%lCIHjm(Gm=3OJ%9FCH_?YWwfI|R z@C0%;xQl+bzHzMuX|OS320e;&Vahf3m^_(~=bJ}sfO0<$6@%v?s$uy9y^AEyC^j)p z1uXkCh7y(mSOcvm;bRF)cZ?90R1%{P$3NB@TyqlV7!8_9=>s5L|75Q@bad+a_oR4( z6fHmjeXii-N-I<6S17~djnBCVLmB(ITMWb7_4DW@t%LBFX!Jcs&}afV0_LAQPASKX zK-o)j9uq!6p$jSWU^B_*`@Uhe;4xu58Fd~mmV6e~7Ln>Bp^Dy_qdJe;#z$H)?+@%@ zncgQGbo~C=1G0i3{Q&}o6fmetF=7Y%lIJ~?Ye<3B<*KgCh zjs`(;p$6d1HFwWpCd+SnZgV<9l>SZ6Zy0)h z)AIsL>jJn{L=IA=bqARO=6e9KuF>V;h^VJ*MD#I=ey1@-oBhyE@Ml}x#M)T}v8aGT zdYq&~g*5!zEgaxBiAT+nHwNR$dHpL#o`2Z_T@XJIqB`?%8L1OVM`K4n@v#H?Rt0=3Ww`qJgMFms&G`1 z{dQELcUBSS`}+w7z~}}jR}Y$pM(G~(cF?_sR(~X{naTkvzUhBI>Z;TdMXN9wTL{bb;AAymio<+tc0a$OOJ(pjKHLsEYTY6$CyZJJKWLRcuIu+`=MNf)+Mf7J>YN?~h@9?@!mz)315V}w-9 zPU3)hf(L^$a1H)c{t;1$6!ox(GJ9@g3aZDtIzcH(L7{q>RE0%-uUC+5r8dAS*-?&z zKsoC!=wVJK^T|Z9rWng~!1r8RNz}iQjjlv}imj$j)K2hhxY?W1MdtxaooLjUpf3Yd zA6$0=Ma&T2_qxlwrRd!@WKAV&#PKt{?SnBeK}EOTSJ1~B-GNAYMz^!a!uCYG^-v5A zLT0{=F8P%yzdNb-fEx1BrJs}^M2^NBmguhKd<{qULkuOlLv|p7k0A&W-98v0y3<){aXWm zZG5?ws~Mfw7fnXU3_-rQT_|55<=3D@9yG%_1Ls9Y@myO>MB8)n&_ElkBew4vP;bnV z1ZyzvOE?=DfqapWLjbA$)(8|)euKDj>s))9iqVdk0te6$&%wN~!V`#|kLVGu#d83# z%u%H-{V<)x=jw|ewy&i|yc<&tEkelr8{!34DA|l&Sg$DGaVU4MC*@ub<-4Su1xlFE z5WTOiixqH2Ei)$-$j)p8t~ooXhE#tk zMU_{g4gg<^8VG9X3UZ)Pp(y)(_}rDbyMpNmp|t|OlF9laMi6-vR1jH#BC|kbR97IP zKcwi7>d{Iw9n+f)-!Frxpgt`Us*gxDMW|wS1^QPBAA!*p1AS3Gg?k0LQ@|aS9XQF0 zTI-bn6~TYdLSf04lalI)RydBI5%XGI$n*Ah2-XZ(tUcHSGeJB!jnzKv!7&(mJh%=u z!WxJOhzCEy2p;TArhs_|n@4LiqZ8RzJ;dN`pe9dK6Wpf{iynvGO!A~W+a)JY>J-9I z^5iHgmURnW5s^DFg2-E{!Zu->*9Ib;6DbiDq^Qt?6lLznm3kdJ^DSvTZ8?VY&k%@Rim|0>qOFe%UDCe?MzjTLb2O-m< zbwRx7F5o~}AHm+?$B1GF;pacs>j?h%i#aX22W+thDTMM_ z-Q$u!DeJr1MD!ephs@vMAZK11%#A2E~+p1cNG zS`Pt|3?7LQGI$e-aXtWMYq|tacYs4FD%)6yN>rk9!Z79k9B`U`X8Voa%9>@O@>)RsN$c|UM|o@nR)td z$kJZQ;5G1uv#1GgA@b<+%-hZI86iuo%Bv%M0$X#rKo*=mWIa>nddL(pA)gC)sl) zkMV1g!%!^DT$aplf*C3|VdAUPhk957#XBun6~oz34@2?JNYnwV65=D?8GsSIQ-s6; z^B-ozi@4@=jOp}FHHxaPM8%0-oQ;dw$fzgy{XLa)-hzfskrUP$WW821+C%`9{mhdM z*MS^1k3Yq@@Rcw|XG2GvscCz2LvyjWpvT^_@wUA$e*v2sAUtC4D2!n5uWYdc<{|uJ z&A>G$8%EIHM9O{`vf)|_9j+ENkgF7bHCDwVs%kM?)RSx}_QOvis*7qVLP}H(Fk7WX zl>M|HMLkSW-_@Wf(@?Ipd{1E*Uc=Pf62+29y%^MzFnQg-5mN_o@*v(GYj=NFk_u;2 zay~1ZQSMah#s6dP&Euo2uDJ08G7yAuf-)KxWYi#wf{}<4BbtE(o`H!*7KsWbF$5Bg zBqlQw6%b6KjE`frRjbunYi-@vRt4M=q7W7Vu~m@P;?nks-y<~Ze?E~@2AdviBb9Kh z36vT~8x{LrOF?zhQ3utNWWt&timj0sKdYWS*3%NY)~3Ixh8YC$%;`dAgyId`#A#fPL|^RLFbPD%Z|u$i^h6{3Vc^3i-jL-pnDW$pDo)CUKA2a|u*6$-PPz zK1%R%yg>z{#^C3$>_kwWguaW9!SN3uD`W5#Sl1T$D1!1da*)YoEF5+}OC#}He2du> z0;-Cjo*XMAmRt+kX{_PUjUw%YOP6i7qYHTAUI~g zBnRJq_K5K9Tqv<5zP$?^ZN9znw0ibf-$-Ca&!mD*4V&CMhJa=DvJ)jz=?YFg^>o72 zSq>pd;nW~-h@AR&625h8{603G%zE5|jjqO~&O6DdYgzVclm#JPqTUkC`l;9`%TQV< zC?%U&axzK+uR-lXg_7S06)sPe-nS8Aw5hQADVqvkAx<2dAf(Cb*yNtmNCmkp<~5W^ z!5P3FeJVj*r}ZR4e@GvR@KqAJOWF2aY`e!4f*%a@L*h;MpMV>F4Gh0!m&;HZ?2xoj z02>1F!ecFOO+feTbkOP+Ht9u^sQL?3l>y}34dV~L`vy)4t)yg#C6Dd}IA-^h$lM`* zX=qd)erG88w@>lgL-AiYj{j^m822Xt2Tu1qK>=}I2!yz9fFDJD6{Hia?jx^%POMg( zDjXcmLTXT!!Eo6BiBVPfPe7TaMKzj>p6%<*wFZVdwaWn|uu97g78EE0APrSnli z(SQ+Y@WyQXn4|0U2MF{b0v!aPQTJKEhU%MiR=WF_EWxWAyFVK(BAE9i(dt5Hyw8)Y z2cOg(kdjZaWIIYiDr#Z!>JFR&nGmfK#Q2SCm5B?G6|M41=s2qs>=4|4f*f!+SUBwN zh81Kzf^YgatzEA_M5JCMsM!kC_Z;(zRt4~ngjO$T1*TT~9KS&}{+o`~P(#*k^jYA| zK@RYiD=l^auCR3`;E`7LZ#rtAFB9nQQPRIq9O!$fDg7Ht<2i1*9FDB~y2PK@zXluL zdey%@n4!?W`%u|>6W{!ZGy|TVW2KX;39kY0L<@CUPs3V?sRt?X3QJrd81ZNB5`Gkr z!-`TSKadr_zzgGet5q%S=y^)od4uirBP7P9efV`Rl;e$Gqs|gJkN?n_JrLFGbmVg+ z{U*P;599msL|N!$i+>o|+xT|8_9#h+o8sLwF--mZVeA)@D!$+ z(c=6|QpqhWS%Q)fxxKJAwH$E%5|*3<@kwCGk;sb3ZG;JD{RJHs5qK3jh`=|nDZ!FO zWXTyK@R}RHp~$^YP#=$oo!XB6E`b|TVkb+qqXdxo`Z2PNYEvE9{)qX|6s#3E7GPFV zFX!S3FFn?~m$R+?YSc+vAF-_f+Dg@r!V>)Kaw1FI{{oTZr^Xd4<^!1M6&aR)V^gD~ zsU+qCl}>b3lk5)2qmb;`B=2P6L$-JFb0BLy0a6ReLdbz+H!1IACMsLs<6CT$K0=ax zMaa*dA_OUmgL)07ser0WQV8Sc*$QD6L7i`dnxa6RuN1;^RJML5p!7vT0_tmmDgr2d zTVCaFiHw$UDe*6sI7uNh^HFjKQ@cJ+Kbd(Pr!NTwJ=Tj0IPQq^>OZ_K@ zT}{RB9%?Lw-%R*z!ohR!kbvK*$O?XaFjlRlAhzK5Z>92_ER6F*NUV48Er#Fkh@YE~ zZvteHV&)^{51q&jsH(R^eK-Tn!I1bek+o9wXjYxt8`AF8&`_eQ)X12Ix^ZS4%X%)U zm+Z#^1?6`;H{?@8IT~RsCRvgp%&E2w6@;C|XOH#dxd~DygD;05o;o>k^Y7bM28yY% zE@e((nUyF5uxGGcMdaVXiW4Hwrqvo3f+@%fk;gm^LS}=bLgZn{K?p{&aM)do%2pk| z#fbbciF`Ui4FxE@`F9!!E!*QqJ*+qXcHs@0xevyG-u!zH9%b|IizxHDG;;=7_HpUaz}SPSY~2P09J4s=qdj7l6cRuX z08-2`HLca<7>PGSLQJ;9FhL*}X3-wl#uB6{|4kyRi`Za}G?=tr50bx*8k*#tm;of7 zyGBptDkAQD64|6*W<2NDAnz|hM)D5HzNwp5(_eeq4%=khyheRXIL?e3Uca?IDG)N1%H0xFG@ zb!<>f{2K8Q0ae4U^|e7=s=D?rzJfDLP}!Ozp!82n3aEtyl?hNjQ?8{io$?Q&9 zphbuMtq&zi!ZmEqCwL{zP7s1mNF=3AcGx_6G-=YEc&|O_K8hh^Z3GoWChp^a3OlY> zlkWZG(Fr1!nsCoj9Bv@wttW^$G{-?L#efnS9Ksm`JknOU1KGG0{#V#6)}=PQcaQ_T zkE#B`?gF%6J%ew_R=5CNN}!i2pr<}arqLf6jQYO(LfQZAM;|axtoxO!uRI>E7D@dZ zS^rq6pJFqEU@uTm6v4iN%9mc8MPDr5ixJ4id(r(MFue=J7pm<-4!y`=jj;P^v|w3e zbdoP2SlmP`?iwnjn-~YW9b-bo``0vPW8yvjr^t$UKMqx3<=F7{&_3@JqJw*W*Zrq>29=?(j}<hzDse#|Hfmv+8bbJQ` zSqtq47`8Hj`Ct-Ke)N*=IkXTHmvlFP{nnpB4w2hekb@izVI{~BH9_vsI4@!wU!Uiw ze~O@Y9vd^Y_uiMleJSw_OT3H{K+Xau5~v+x`Zm5-4$*8VX(b8M@g$P4_M!x>DQ&*Q zHmlfXFG8Sbl;RY92tvXsvKeq80LG`!HEeDOnoD6NFn)$qP&(jAJ9IG)9%6hrPCOY| z8ICt`wjm#di~%*M#z^4evZ*UC$Ff_vuG`jSV{1?Q$3xKGa*#@0B`xY}FxrYU=PTBK?5T68JmdW6(KA(xj{Ko z^BTX$4)d0Wp#JGhoreymMuQCVRTZx_-=#xU0EHfND8$=v6Ub=4drNVk(&;~~_5Ky=?_&vN^ILFeXq zkVWK6N)BhqYf%!?F^o8<(X<(APG+}*oblqb+vkiBCC+Zsp1^tZnh z&`nBB527-9pUlu<_LyfVpmPa&xdJ^Z4tfzL2@&DHP^{xN;TB{gd2o4y>}{3}a-r(& zb1WQopMlEOe0=kpw~3_0L|H(NBSo{0A?A{CIV?B>=F}p!P83c8O z0+n|sImR`zV^Gz{U(W7ty?(w@`&)jh1dL`QEH{9MRW40TV-v&BL{FnG{JLZ=Jjpl*P1Bctk{ zuzm0P;0f3cJrjBi0Ih>oKaN(-#u-Xa)MWu{KSyQHV2bE?c+~E%acTJ)jXch_5%UhFC(MRvr?g3buEw zVC2XnVDp{$c*S8CrR^1BM=HeNwh{TzB_3co(i$Ga()NyoP*<_xj>Cy)ip6Flx-St? zFk#kD!AEhCY%LOXKlYQvkzLO=uST0GiUKppqqo~L$Y1V;9H`HWnj$6cS>s0i8t3??VnEH$#csacIFhoH7-Y7p|zjPL*&y zfv$1JjPCbuV==X?3Vp9+LrN}T$vaRI=yj0NDVSI+VY zWAUyIZfkM?w< z#t-{1g>PAAeC)_(f_gxVGworvb|w)^6$QtZhd}_vw7!T@2qiD&+!fcq(~(W0uGR8DET>ZpyY5?3cFwDw3$w+i%YqpWILJo6ft??Fw({`GY;B9+4Y#6~)_5E4681Ul_=2s3-M>Q%RtVqXeBmGzpwAHKcmUN3dPXQ=tVoIHSmH>9 zR*?y+Ga|&{VY|Jj^Q8(<#=x}0L6)3)n87sF+NJetJv_G0eGEkaf7W!NUvPj z{#J_lzPT_J%U9Xh)jb;nSB=n9V$h`+?-OoQJKykQFUmE8kB$8=w?=%(OT z&&dY&H{mPry9AXjeUS|Ch$C;wwc zmNc=0O{_r^M80?5ItQduzO`&;dvRrA=XbIG^@75oeCt7+@WM{_3Fr~-XS*ZCxBdbH zl4F9t_0F5sv&V9I;uwQk7%Adv{f*!T0$ieRU4 z6H=JViuXaRWmz#32*oA!0O7pt0Q^)n>wE(ShxM)42ue&8K^+!f6_(hzmui1M~1#xzkTp}1H#SL!-;J`iKu>#$*D+yohS ziLq_W0%T>}6rLayH}vHH3Z@U*Iu2x96(UV5Y$_Eg2*k3gNoP^ zvWC`I4Al51krhz?Y(;akZBU;g2T)-a4!fVBgglOKF$ob+#}U+}03|N#+t$wuRR33r zCf2U2lpHGkXUP=Kf{{Hmi+h+%sOupmGAKQ5nhiqA6WP??AfPEq9m8)9>WOH%zu}YC z%2D@UTN4{NnGHOG22kUh6?TojH<9BnCY8)#$?FLUzw<})NDVd*yh53(Z%j6N8d8m( zIV5Qxa9z0PQzV_HjGkRctcxiTsZ;e~Ak!OT2s+wFKtD#MszAT^Gc7Q$a_q;s_%yP@ z#XsMSW`BYf1mqUvz{Q`iaM<09%GM|N7UQCTI-Q_+)gF2|F%D`59z{02)blY=V;Daa zP?uoRuySlr(~$$HAuJqryHVL{7EoF?1=JY?#h)sX9Y0&F1^MhhO*zqmQYMdO_yb)j zav^KG$!bA6SZOO{3?#I1Hrwb(mo7~T(K&(2vBPsZmOh&AvC#; zmsLE{>YUIM#Yt@b3O1i=S8%7FZ41P=)@y5q+wA@j2ARzDqQ8ur62)=~8+G<<6!;AT z<1ooQG=y~>$AHpF8(>yajq6D!uv|TRtS1nyj+SjBk{T zd01^50#2i4RC=(#VR|#Mg_2*yNbKbctXyox?NNct(mh_|NAn1FtbmQ%kN%vp-pYO& zIKtO*T26Y(VLCs5s4*2F)OcX9Pjxdvd|D>@F|5)81xCxnUqJb%1%~)BgNB_`ek#U- z`M!1AWu%pJIENpaox+YA>m9Vw_%Cu=)cwv1(y=`_8s%PFj_0tuAL`3=Jrt8?WUyh9 z3<(ho$lkl~ON@Oxj%(kyBihC2#6xJ#XnC{3TkgHwJI_0}{PKC7n{m|1o9Q=~-+_-M z&=q}s(cMOL_!O)JY?goADV{mUX!+b@m@{G{~C?XfaMl- ze~OO#O=mGOCFVu=5uYQCP=9K>BSj&|e)mAm1O+1M4wG*9dPH8k0&T`V8njQ7%6IpV zMxz=jbTq5TG_w3=X{L8?hbNGcw;_^Y;MP;*`ULu6K>MN}<3GDR=|v|ci=D`3OvU59 znDq0R2YlE~Y5vnNcjBH@kOp;yEMU*OQ0+J$NGv5F6u14tg1ej_w!tr2ZE3f@}scb;>^Uc`ZD*c+YVF+jPNQ)SrA%;c9Dx!&jn zcnv;CZ|guEP@z!i5U|2~IprZ4|2f`^y<|j%VP1zzJofm_YqI_3w}yEMTI$AmY(R?^ zdO#uM9WNtSRFJt0H^Msahee5b`35SPK>xh{JxnYjedVfP=yYz+fj z?hooIT&Y7mWqfmZ8RoZp3$r|i*^mi*cX4!Gk{xw75)-?B^N>ORPDcMG0bRM>Phmkz;PKHG@E}w)*I$US?08?y&ai>qYOq>Hd&nz^n{{jN6YT;L`p``YnYQVm1+{=U6u{aB<-V~ zf)>can22smsGpQsEf_&nR$j#fOdTHYrh0bf|6cB32CSvD&2gER! zgV3Dg=b*n^p=_kCCXlX56)F4|)$TVhDuY(30Jm$5&_!kbkhj7g^3`A=k+bw@nWZOT zAZ(-wK#PG;2x6*$;LBZnsgzv&_M;?*fB|Jjs1K3~UkDxZ*7!o{z(2&--U|F*lQaVn zKdA0HG7%cU)_-JsB0%T;*y#8*PbDU>7sah|2f?TOdYcmp%P}hpyH^DC##a1PA}>-M7L<6cYjZ zPst0rk467wV?C70%>dGkjR3@SV*m;4tP-Q3J8&+INpmIZw{5uY#C>gcO940ML4@m$ zL~CjpHZUvVbglX5gr+JZT8ww!$t;7Z@;MQ8g)@J<3$smNWYnF{N7JY=3cd~;V?_Hw z&}({{e3ZyZB9XwwmPk3Pv;llWKR#f1i<tbp_j^|*oVAMt3A4<6$w6q#P!pxS{!j~lj(EG#C5>3^q9{ix4Col%DMks>Z3oiT3 zsn8}M%FmhrDrHQ=ff1|Sz%Cn@YvL00P`?n7eT|y3U!oDNWEyC>d=YZdUyCqWX5jRpkEW8rH)v!Cz!hCqVCw6unmnz1M|) zLQ{ds2^uPfA0{8c?|6s?@B`&4DOaJ%6Nq)cL=?mdzDzZu;CBFg;7raNv9X>Nz%chs z05ZN%DcVSNaWp2NayK~?c0YkAp1{2ieOLvH8M8nVs?udpuTTi%EffTP06xkRe&K(E zU#sBHu;Cx`1Mn+A5YXBYY9OuC5{Q||?_5n!u(*LN3{A%Tl0r!FSTrFuL*xAko(Q6R zaWjeHTxSd7QoxMUCW+vlAVDLE z!%Yw=JQ6M2SSJh^yMHSLkQy>)82Kw60{Fm*)_1U~5CqAzaW~9ZNA00K0~oO5Y8WT* zoBbItAK4#L1pN`h{FnY@^z4sE`t!2}>Cd@#ed~JuJ^K@5l~z?ZUEO2N3`~ANl9hbK_#-t` ze_;H7LAoXkzfg;OkFg;pV{v;;2Pt;q{JH7FnBRcFQ|PLSlt|KakNw4y`bCBw>tL8C zMW3dNI^-8<(&R6Nc58*HU!dU?2ABYn>y+AGN>jg-*RWtoZ@$RPX2yF0}Y+?X%^&~-{fD_yv$>mE@G1$ql>OHTGnS4G&L{T z4VSwCzZ+LaNkJ`;4Yt7CoCz3XFmXVr#Hf$We}qKtV~v&@My3S@(1CMbBrR;RjuFpi zlMFz_rbgp+jQ!$IKt0vjQ5I-%iL&@AU@{ZU!+qv9Z}dGF&TXT_swj6J5-p1ehgi(w-!9GyD8=bc|zo~iI$#(omm=~|%jC1Z2a)=y*+lT6OOTjQP zU?es~s?%`j4=!Yg7J-T1k)rR-iwgZ_2Q0^LSAc%e;lH^ukzGCFOVFntT39}Wy%<;O zE;37D&NO6tTRwJqTRuy7wY~tV;Hi(R^?vn~9+>HE`8FeP0`$`6s{keJb|54#dTCHC zZVqnmeg!45fr8xMfcx=l@D~0w^VfP)tG%_Mye5EdaA&YYx zMn>ND$U;Cl9|iqpG4OMKif)yd3g&K;NOp>i8PgxDGo_=0C=a2@&|2-mLAJ{HisVJ;5A>bfuzqqgX=1EzS&oFYq?i_C zBXp-oMYNB4fxMbPiS2(0Z#{|qe`g;uRZf}t3iJklSkLNMa8Y z+Wqiup==BBjB8XT*Z4zCr9QZ?5JZ$uH$v0PpjShan_<5#XCFu=ZP;mxPVJP(OZE}# zuOc-P~)4Py% zq5DX-m4p%2#r`hh1BFdOh0k2;3(wpZb+4$Vcjjun2<%FT?;;?EP_aJ;T5@~9ZJ2BQ z`I&)hphGf^mX1vF{Y#%j-9C)_Hm=rLXoMA-4f8Nx!G^$Wl*uyky;;E#*fSV)XP~R* zer_6oUtYtqm@v*mB>@GJ!#jd>w{!x+_TU;i`b9Y&->F-Sjstytp^UBFx1tO35=2gT zZW#1$zTN!|ZFAnLxqSdM9e6ps{p89F3i%KGAqth=U#jjS4}b;KSg{jDx$}jfZL2UKsp=7&CRZCE|GBa%gf*c~ z40}t$rp|QW;s9A z-VgEzCSwdCP~w+x=QbH+Si=j|cn})1CR)^g41VrOicF>iFgRoi4c-=!8tBQ5&8&(> zTEE-tUxs;2CgO}n!T6KGJcMLit(NqCya^10Qz8B;c-vu}-?AsYxNU>0r~^o2B3K)N zioohhUxbyXX1Q8+2^)*nXNwmn^Gm`S*tHl=dtI$!ue2=7PII+BiSlSKP>#^zby$vq zB54oIK-?G+lVL_*a2}iIFgR+;Ex2SuI6yltBsCGIJ z)xAyZ-i7GiCZpiOtj0MQb-2$>h{S0wI3zC`Ta8HQr_8VJFA2Ao2xV_I7?+Cm&&=r3 zzMx*ivF9IXA2=^2>Mi>YBY$wf%OyYPI;@2)`3eJB8gdO=4u(NQmZz~U+8Inx zU%{!X099OfwMQJX@&GO#1BfFTpTnF0%gZ|w3!E(<{UkKqW49I?u*vp@jKl0$P+S>q z`(bo2Hjaj8nLba;fy|&2MmLR&ZQY*$rxgc?TJXrCuy+OCa{QIzQ{CVKZy@uUaN((&o1FDD7a z&RHOHLKsHYH|){gAN8R}FUYoLe2Srt z1>7D(`!9yQKw?jkvDvY_6Bh7JFg}5v_R_GJZqRz>XN}YuCJ3Cr48sp+nF|=p|@=VYc=7C)7!_$wVjFHkp=U=pb42W%Cf6gr!KqQOUF4 zbenq!WG7Z*T&)PxrkRcq-n8t`2p$Flk|KviZ?yn*1QEdfs@K3yvp)!1-NIIP13s{b z{?@X;ZxHsO`;yex>HKkN_oReos9?g*JzoJ8R_=bCrX*ca&@F#F-v_a}>)eV5s}XBy zP)$BfDY!7u2Xom8QRAmUT??Ujf*yo&zQ9ULKPIhW`a5y)YJ%u%x=hDI%;0>qV>8IdWRDNTC1L)hi8ecKt=4AZD$o*he-T!(aFZHl zVJvjDi9uZ8I0JGV7|LOO7*`MXcMpT2iMo%yOlaIa7`c-C-)15S4wfC$X`l~B>pZ+t zI}M}mCGnx=hbHB=3V(t7JT`qM9>(Bv;8YND{O=@+=5sDw};N z{~NrD2`ko8WSrlFv8({c<{t!k#HPc_dXms$dttG8z-xYA!jXtD(n*5U9>{^KbpS-8 zr^1#+Bw18_Xg5TMoI_p64Ybl0$x&kjjiPV^EUKtW3~H;7=$GI!5bOOicEd3dktkow z_vxVG)d=`=(K76Q67SD_nw&InTU6@AN4ktHE$LcvqFcw^`-;pL%j(NL6$Iu82od8S6)w&h$ z>9~~gV=3Glt5|h^xNJSc_+#wh&JS(fy@P8Dw(gFg5KDjr$FbO&n2MME3HDMg#ujHG z0&nM-(X*ip`~t@q;24+y7vm|AAKapGx#419+ndoS+I@XeBjPjXCcTnUHXIC@>(Si$ zbfvqnK6xZt5A|b|gucC9FonFm#m@>`Ud>q!ia}puhuI!6D0aG9IRoQ<)Y)jZzzRU) zILp-NtK`ZFMQb;{3IDs-0u6eM!1z59zF9h)29(H-m(Y@uD6qa++y|!EZzmxL_#CZE zgtbLz0BRMba*a@W_dCn&!C@6y7BjE6jbH& zJJ(BN16XtEX#Ayy^&p4<#V`vC8KMrt?mO$rkl)*tBc--G>i(5{xi9tw3ozG!E)a%V zc$tXmB*o-IIN*J1#A$?F5hxG*ax?;4GHXzpF*52n69h05w7glEYTnuMV-He$kJ&q% z+T2rTs_26&^bVTlBgkdh_Mtqa6}=S34)06bi}Kt(mrmV@OO2v&%a^v&+lb z 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 Y<4U^O1|=cmlc3 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_descriptors=(Field, FieldInfo)) +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 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, '__fields__') 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}) + 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 .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/mypy.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/mypy.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..4c2adf0f6fe488b5e32c076b6b667d790ee05661 GIT binary patch literal 318464 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

    ^&ok2^BCb4%9A67 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

      8|sEMspYrPBk~!g}sQ?!mP< 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 W|CI{ti5)t6?h(?:\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() + quote_plus: bool = False + + __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 += cls.quote(user) + if password: + url += ':' + cls.quote(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 += '/'.join(map(cls.quote, path.split('/'))) + if query: + queries = query.split('&') + url += '?' + '&'.join(map(lambda s: '='.join(map(cls.quote, s.split('='))), queries)) + 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 + + @classmethod + def quote(cls, string: str, safe: str = '') -> str: + return quote_plus(string, safe) if cls.quote_plus else quote(string, safe) + + 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+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, + quote_plus: bool = False, +) -> 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, + quote_plus=quote_plus, + ) + 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 ]*?) *<(.*)> *') + + +def validate_email(value: Union[str]) -> Tuple[str, str]: + """ + Brutally simple email address validation. Note unlike most email address validation + * raw ip address (literal) domain parts are not allowed. + * "John Doe " style "pretty" email addresses are processed + * the local part check is extremely basic. This raises the possibility of unicode spoofing, but no better + solution is really possible. + * spaces are striped from the beginning and end of addresses but no error is raised + + See RFC 5322 but treat it with suspicion, there seems to exist no universally acknowledged test for a valid email! + """ + if email_validator is None: + import_email_validator() + + m = pretty_email_regex.fullmatch(value) + name: Optional[str] = None + if m: + name, value = m.groups() + + email = value.strip() + + try: + email_validator.validate_email(email, check_deliverability=False) + except email_validator.EmailNotValidError as e: + raise errors.EmailError() from e + + 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/parse.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/parse.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..2c71c861e57ea7bdb91fff40624dc3b2da41a222 GIT binary patch literal 50176 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/parse.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/parse.py new file mode 100644 index 00000000..7ac330ca --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/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 .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/schema.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/schema.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..30974e35486bee2c4fdf1ed2c59dec5f1d6caf01 GIT binary patch literal 346624 zcmd?Sd3;pG(mx!Qfw&A4mH}MQQG-SiL}L^T(Huzdj7|WNO$CgKiVBL7(I|^xGRk-y z754=d_uY&4q9TMOAWLL-0Z~A3y=M#{iXx~mzwfuY&&*_IxX*Ln_x=6#^3lv$s;jH3 ztE;Q3tNWB)`e0UztgNh-_&*lQ%9@8?{wtQh|M^c&v#hK($Ifq)HTRI!$IWXNSbf}( zvDZ!XO}OQzYj3$?yziQl@;mjxypgrm36%Du;y)! z%Q_QW>WfC>-?U!1&QX{0gxAfpvRcWb#BWx;OEFhomjhH4a(>e9)ss0dwaglcGKat1 zGHVQR&UR((EMR-~)9gFwGSYzFuq z6<1eQ;CVy7ZYSH0|C0atva-s1+%o2hiYv0R{&_v#5a&4jk~c~JiXl!t6j;{A_wk}0 z?`Pl_ZA|`Gj5j?dC_rf=+M3l45U1id>0dGN-7@hOc98G{ydm$i&dmgO^|+e=NFHT@ zS6PSRw>S;1FP{GY@?Y`AX4Q6|X)QLaji&X9X*I;Wc}B}DYh9?m(vx3rHB|l8-1Eqy z!cRPp)SFdHe3yN+D*0c)x+JGG|5MX4e5KZ6^OL=S!i|RKx%xowOMLiUTpC(j(b0@G z2SDcw!W}mHBmJ70VIwEM{v$Ki^~Sy}vy!o`T2*}U&|$-kA;vIcI0!2@E!UO*Xqjc^ zFEPU+*Y0ar1AFriJJ`-cK)AmTc?w58OH`tkyi04j}mhwf~d6+jbw_EF1P zWQFQ)KXiWJu&k`;Z>+)syQE>!_R@ZL9czfV%)$6sUXt6BVRM7l5N~%4 z;^Q1)T8G5EPoLK^YraX`Psk(pEehFR7inaug2=w(y+(GMLbgqVB#;dtvc5ppIKW>O zYf*8vY4y)R;a3Q0xjO+h8r+M;fvP76n#DH}SH!^%n%D$E8S@@E7x*p%zJTR^Xbd6U z?NQj6HyT9QJr8Y}m0#bOD;>{17fFBs1T6Wp+O)p#TdV9mX;>h4gqgp}KI(X&sajHQ zTyBguMqWO8RMP=qT1x_9(-#OAcOGU8fyj<9!y_;vzBj{TZNu7bhAX$3)}Mj!*o~#u z_CR>TIs;wSED)}22!zL=1M$Zf^L7U#Oo(%+K3E#C3N~ETGAmMfg;6&RZSh;bnIJF^ zjp^U7WmcKBM)+D{EjO$$?8^=Tk07;q5P47aIB2%$aQwl*Ila`CRhnOKS{uw5?gyZ~ zt}b|HhMR%67eeIhHV~GQ-d*41Q)^@JIEvfR;PS1){|0*v-s8n`R|pX7Sjb_pO=J=% z3sD3fqdZmhXcjya9hYrl+zjdong5`K_*U9mm$SIE%8OQIIjx$(vVJIk(?b8=nr((F zzzOSs8E!=m9OAcHX`FDR@{GC{DOT*QGHZKe(p7%+ZD^0Ddh~%d6fY<^l!3p?(Zoq;;v&kxP@!ae zmUMC{I(fBVT^aLsATgrX;tUa?%{Y0mtx*{MY;~msh3u6y_~H?iJw@aKd=T+ zVj4?WoJ+naaG{#(P)IlG9Tcd$2Jel!?JV*;E(6v_!i2SUPZ@rD9qiK`>^lg$f>^6k zS)V%Is!oIW{4E5WkM3EE?uqW;ZLGCvZH3TmW}ADTpB=o=v~ClL>1$e-=TKZIE2l}% zIz`zUX+KmF#H|K2zU*Vl&t4gBvEV@TNesB3pP zNPz;#;i#q(a)z{NRpk22&<;=aqCdfRw$l@OpO+YwO3b3K%A1sODHIEyfYsFnlhz+= znd_JLe(QV;Z8C$J7k?^pdvSs_^;A1Dw-O4ZqOD)?S7`!@b^udxF^3fhR$6lys96&m z+|zF@!7MYv7&*GBePxD6=8AsIp*`d?t$i`?1d%h5nzp7@^!lilS+%9$MD$BAC1APC zb0~)tn0L;m!1Mw6GO^dH2-sjs#I zkI|$JBk>@mO9R$gGvXcxy z3HxpYnAa4LmS@1)>3Bs6Tw+6ELaqGuyQC{IF~|Z=1M(%^$vDj+m>h zIDuk9@G1LrKPvWPQuA94plU|U`yS9k`WvC1V3WQocV6E))KhElTv?x$>?oifBzhJ) zi9VJYTWi81xc>oON4i&h4w$N#>&{;JoA7+owtEME0d zwpsO8-ee-0dOB?o6V}+FP(J}>*acYSdRFZNCVTb*F+E$)U&zj#%)wAei60xV#^jcB zsElA2pp5%HxRd!9j6-t4upzL#ZxPdaEV)Gc?|e4f-3cV2#wRGxs6^~PzKOVg>#rW= zIrg8@zz2YK{%X`t`|nahy01cEB`|i+EQ(9?Ud?2)Fj{dL^#OppLQMRHiz+TG!(4C# zs_sB;M7&!rzz@ydk-*$Y%BuhgnsQ}~6?X>Amw+j={17qW1AuQM@ClrRdX`zM%)j6B>gd#C$j}sS&rGeG&|@E6#n9goC4+JhXIP=%~BUw zeRg45^T(Doo+R%N#d|#bRX=QpX~T$p&R(O3caxM}Yldrbr%9bLGxTwVTg)TOjYhUu zGVaZ#wEgze{WW{L`kSt-;0++h8^938VDpG+-lY|8qb~ss1niuPIl2oj%;yj0Ndx>y zGaN^q&gRGza68I$Wa}c{v*GImtYspwy8+QS1c;g|L;0+0M45tun;60tQ z?tk}(1at*cjhbQzd1Jt+DdKMl8fes<#>?I@?=W^B3*L<3g!%n35rYQPYG?P`Lgia= zSj^iN52J$sVAPz1azKDVR6SIWwYa{?Ag$0U7*ZVbgZO6x|CszUmVbKkPcQyS*A~zc z5PwhgEeNwk%kc+X_@##{tFg?qy4bjY2NtmUK>}CyL=#}xTdqZY`B)^d_B>pMyZ=F% zgy96+u@nk4=Dh}eCL;KRpj>IMo=cg4uLH}jTAsNsJ&hu$+!l!7D2U*u3W(qoh#=e+ zc!WQvi6Dju9KyBsff|ZnH^{=SrVgQ>BX70+buFvIyuKesTd)iG*k=g%NE_Cuxk@n? z9E(oMrg)|r)0X>dcx;q{30ev|B0>o-+j4DTgV9}wtKMIO+s4u0SrH5+;n|tEi1X}m zHc@yMAwtEo6)?HLvxfy!63@<{Oi<7VktmF#C;ye;Ss!`kI6KbH7gK;s^y$*)L1ATb)g9XYa6Gd zu`%zMB*@u>v;^{TLT+LW&UDJjcBNPm_Fj+UKoyN=k^7{`i!AaQid6K#$T~BRLm0N? z+L(85_c(kJ;Ufb7HsLFE6}#|=ynZHux*b997tlI_mN}@8OG5oj0`<2S0iM>HQS&k3 zy8zxFLkt6R9OiKNGiAMR%<KSk!ErVXP zfkU6t+c-tsqrTauwL(oy{U|p|H|3qBXQdeQ7Nt_nO5JziHu^FufndJG3CrrT{|x>> z4l>S4%TG~qik`azWu~EVn3bMKxJFnB%V<n{r+

      qmT_5wlrr$p&?;&I8zSZ_!m|X)BEb~;~K@-Q(Cs1vOiws8a`Lt$!YX{xj z_%sFG1?80N`9dJzn_^P*wj~1!7kjE#k-kFL?WopM&7iXcxL-IKuQ7=7IGD%_ix!Qz zrG9G|a45I5Bo~*f#L|KlGiMu$$DkV(`?`t|w92SM3+1t5H{&xXWYpnT9y2)Qsr~~{ zc+BDrd=PpU59}kMFUZX`d|P#DZnNNFesG+%iljOcJsEQk{D`rQem^Jts(mdyq4umO zf*@ew;^3ivYpTz0-I&L?(@`)%z_uGO2OPyY05%Aw6sL9M5JQ!m%koT%o*c~T;!Fly zAh(j-L}(qZ%paK`uq?s(0jNf(cF_pTYZinNSWF|Z3?1I#I33N^ zM1e-97Hg_VkclyE_xvaUcnAUUqMTh;PCCE>#5hq-OijPFjB;9RTI;|#bXUx4po7WS zT66+K6odSQx8`{6Tk#i72ZSwBxq))_mP4gXcm=A%Y&W0`I*A68QS(e2=%n%Bcaz3p zl;3iajPj!pdN<}lZb2pndIg>uHJ7pwmmSkPR(NlB5tlKDmanxxnco6Mu4EB6iWoJ6 zc-b76wND8N_wxP^T-H7*_fvWQZ{Bk$!l;?Z`!8@g6`kt->O`Td3fd=$uFZIA)SN}g z7Xb-IR=VurQnNg~Uods!`zl=4K8!y?s!?-19)hurmB|l}&=0Rlewd>l4oH63T0iWa z{LrNz<{CA7q4XOMhkzJ0J8=n_LS;1GD5SMBNrzRm@Io{SV&H4)XV4sq077(zCv+Dt zMHOJqhn5xt{Ah($L5W9=*yFlt@}G2$I#xCCG|!B?-O6JJhCyEsZU z1`^I;0X3UXAjudPMJMvv3_&tfXx{?bVYpLBn}z^0M(fHL5lal5$jkvyu3x1y zj$z64nFU7DM)aQFT6&PMLwu1oJs$ZX$9&A&$aOO1kzzTer~{UFYX5>jHPYREzbjtS z&vCuQt8l;0xO|r-{8PjF9bZ5*@7C4ia6f9|SdOQ5sTY zOvvAa!1TIY27+vihYiQ!HG+g#t}d~@Gp#&M4^Z8Drh!idb1j$>JBWuhGB=IqoGe!i-$no(h(FzdAMv@MQwh&#TAC2Vl7dJRhOA523<|5szj4 z+k}nj`j})-&c*uot9t!=4CEvFo)7`vOY~7x3WqhuJGvr&Q*h<`Q z3KhigR+OtXEC->-+s{B%RevJ7FeJC9F%LE%j9mBMeCi1_Ab9x+FVWRlu=VcXwdEdw z=FCF}W*MHcdNiRHkIOt|4Q!eZ_djw}aM~>LA%J-YC`U~4lTtj4xWB?XCC&Ctjg;l6 zBIf#@A_Wux^u1Zw{fc7|Z*u~gLm&Z70-F8E(TMkO#=}{Y1?a|ppzWW41PK=l2@=rE z229g{<|_p5Nc{>q_Q9foDPy0`mSe=zOA0`lB7nKGIkC^mZ4eeNnUEU2lz2O`JBFLn zw=1jJRTV)I6=auEu$Oy+Q(Qr3)`lxD;x+)O0skQ2IVRU9UU?_1giz#^ zSKcKXw~eDfLmfo3F#yH$J}zLcV_^fr+zfps?RWigIv-0U<35NxVri?nl$aDtdxis& zChwh4iHtn7e2KFRtmsXi>Ko*lYvwV4NyO47b*4T*AY)<7?_v11;8x@j)Nz%-sQZw^;8jR4C3sbUfhxR;k}B|O*7FHot(Rx6laKyyc@=wO?$hmU|FfV4Ig z1I34e;%}g!NeY(Iri-|1ARJs{GMN^Gxw{wAVyF~~ksCvp5xg0}t3kXP#H(^%mD|Vt zNLmA&8zfFE(<#!w7=i2D*Cbf)x*GS-$vsX{ehydSNdzJyvAT6rXNw!4@E4Xo&; z#(L0{Tco&(hdo1rmGrV~Blu0{-v>{85A-r{O0k_#ZkF{_zC-X1J@G z`lAWoN8mC15OZ5&kA7Jal$@sigTRU{T?y?j1;o=(pq$k;pbullaULZ{{d~ z{w-XAWX$Lth$~`7rJ&4H{XA~OuDp@2Au&F+3MTwMB|*dmB;o`Rk(T(NLsm$gDzp9$ zs4$YjKoGmlQ++6Fv(~COl00YEtK=Ga&OnkpXEK?m`YYV>IWRy>PjezDgV2NqM#?Pr z=8m8=;te4LndJR{ji-%=*snt4>)vNRfo92}pI zCTG-Dvi{FA)lUP({uQbhA}*nlS8%PV9?4RNqLiPjn}~{4^qqPv7_bSXfC1GAWF|3S z3!XL}3cnChk1K!#+Vy(GI5n=G#B~*MMaDZZwNXC570hcq+_c7{1*5>>V2)fPo+gpC zR%xA$UXHGo%r*BG*koF}T#Bp((Jo(h#j}KVS%F*8F1L5m+GPSR;@ahDcBE*RnSx8S zOB-fDgbN-JObP9BHnj%08k)^G6{e$SpGs(#`{bFcoA8D4&CQ1OH*?)iancB}Fw-Ax zQ)z?eS_hDc+b3`f4YO!l3$xog%2TE7p6v{9PpBTR>-fj0dx#yw99Im<=BQk~iJ&DnO!U<<6G( z1{k(#&thK?tsBsJ&*J8O>(h$XrTHHtk+FGf9kM3D_+XBv_bJjlfegeG@KO-C1#3-S||C)J+~*bOc+3 zTg&B^wBI+O~=I*G)RBcLwn4_QJEeZ#WatXhR2?7;q&-z_d z%NZD0ZF^y0EkZkux{pzTxEatE938i!F3qaxtov)+d#eA1zbbqWQ^tFJ4kw_rmH(^S zl3$Wjdps(63wbJai=~p!QYvW+bTMx~wq5b}SinzCz^`}UNzv!h%U*9=1_?3UVAgAf zlF*VY)jv_{i{w(zN-5VDq$z?_HjF0dM3s~a&t+5 zDA(AR!GNW7v1cF#P3Nrb%+tL@xBmx+G7$VIT-YXgcJb*jlR(nqyI%GERf#FF5gB() zQ=8K?o$B^jt1|0HF+Mp-z}SR+8eQ;vELOKrI%YfxvkIDlCJ}cTa!EGUSp>ulhS?)*(2zr@EJ%0}HcG_yCW#}PhO&dM@AUaB77%E!w8 zdy|jf!DAKT)A7A=xjCHGI&&+A%8IMnJ_yTpOR>I5*W9`#rwr+5n3#$s84hzHGTxw2 z%Q!v%C}OdU9nfU^#kcbOQlFkX^{xw=tKL;@l$c_AL@DH*VWY(DY6f+ zk_ybZYaY?Tq%v%|igKNp-3$?jK@fd`w^ch49ePBr4&dr;T*>lO#Cs9l)~bDo69t&L z=K6~Fp1@*6i2i{~!}E;nY02})mSCQKOGAr*VER59bc4M87=r;%*$P0sKnO-|jsUCX zj{-r65xt#{hY|NqfEn``p0h9fk};yjj-~}ZW0Qldykc9!YWq064n&ZD=eI8F>9=m^ z<+mml`>pTdK^i8QAs>=mj`)ns9+vC7NvJ_ZIxGD#c0Qvq2y>cMoi2*m;J0Q^<9X9Em#Svu$zGV&4E0l|BS=gf3nE|B=*nFpae%B zPOmR+^1n(%T;(+CW)jh2$h1zn1-_f1(=y;V5;(LX&C!J)X5r?r-O>iSSy=EZC^u*{ ztYXsmBOl?>2S5P>4_7}N#;f|n8V*|-#PTC@H75ex+8Ek&`;i#5tr7%2hB~Nl@8xWs zs$Z<%5Dy9=Rs_o2&r7gLqAZU&p4oVMSlV_9SlvhCR`N!sw8jNhlK zp@K_nrwf295bk~gic%4^^23m$Yxbw=8BYjlS3rUMtC^yC0pzKE8_yC`(|PSPaZSc^&`Msu;{B17OEbX!M^ zCJ<5C4Wi31!anUWZI0Fl%Z$2zk}YFolAel=Vz;)3eV}FWdA_|>*uK`@@Bj-!-gkIH zry;W|8D=nGngjrx+;q;WPFvI5KXM??6B;EdQ>>ln0A3fmUH~n@@nztGVGT+$E`yg? zivnodST?dGa!GU8hiqdx8#or$A=@~?k7aBz6XA}~Of0iLYHBH}A?FGCnV?ozgH|?P zRkf&j%=<<*$KzfqhivTg;EM~`t~SitaN5!6qBG`$Em$mDo4$~C2$#n#_lYkya(QR_ ztOTQPH0ss@7Y5<<9$HIKqC>~SzU1_sm(ff($P~??(3?>-S|grN4+*F_wqo>HdDGN) zOxGl^X>LOtAG)Fbc4U+l`~(+O_vhyz)NlQbW<;-Gf?tYy5E-R{=-gy9w#AT7(r-s| zZxIpCOdx&+h@)>I@)q-+&^oR<+b>uxI`dmqZFB?x5^D1tsNp2E&X%R`TE)AmjZyc# z6x|-J2cis3U2EU>liq`qqbvJ2N!cmUpVlyTLQzT`HfoyT))Z1Fa;=oj-%#I+vt>HS zK*|V^qGtgI`z~UC5ZDv#xaF{n?Kn!>AydeiM%}L{r$y;EAr$<(=v1f-)zM52)ff>0 zk1pY@aupI!p^DZLr%pw@0M2q}x`UQ+!@!orHZYrg(o~RvrT9d> zp>Vam{vl0{in*PbAg47EZ02UCbaLR!!C^ucO?`4#(_Tho1)(-?Z5C$-_#Po}663>% zZdifkecjYHz>UFyA;KB7pHu=Wu?fZz8}8r*w!~ERTZ@b>@6wVj7cZ*)g0(UVjuYg6 zM+Y;Arm~Si(V2&2EWf2id=zk~ok$uLniGHq)Nu^I%1oP-G0d2J<-hgt&(UR0B+tHr z-I2<4h!3I@uG>UbX-38%@ZHDq7PAsP(Vju9wu=i&)rk8<)Au#cNc!;!(sLGkDorn8 z{g<+S#YnV!R%VI$K^FLgZ%*OGIGW@s9K#aiZQYltAHA2r zO>iQ_>%mmWYmP2_2?>DYq;)7d^9_g|CoJj8XDEm9u5_Xai8i}qtRpQ5FuGY>{BjmB ziQK5Wl~q0_M%G%p;}3BOQ*SHzwvumChIMF@ShMwCYgoyiM?Xrf39`UGU5B{~#_f_0aXauhEEPy#uyY$cO9TcF!L0-a2kl4D63ee$ z&c{XExV=mFyXC4BTw(#P=fXs|V2zuY5`n>E$YurxCyKqZ(hl8C{RKJ3vcu(gmT2~2 z%`!H7dyEA{Rnnj@I1z%PSbHB@Pjxi+4@imST1o!sSO^Sq6$>f(-^D_1x*wGsY#P8g zmw?Cx4=UB0s$OaQV0IvNk7F%gQ}?u{t|O_-po_MDn<6RCvNH!j5>opwE-7&E5952w z9fL)#jrqf|kP*ZlF;@%SiAPK5t>8EGMB{i(%)P|@t8{_;21vGa>Xo>Nck0_BUAuti zMZqndItNQJ=+xI!I@M1BV5g4PojRvF(W#d->C{&;kN!>v;+@LTU!DuLF@Mmgdk2*2 zX=by;U|hQi`~R?CAHNS}|EGSvg`JNX{y+3<-3f657wUdJS7Jp?RcF$K+Wk*57Zd84 zkY6Y$w{BlOiX$^CMHztYhob}H+9^h%k87u6oQcM(k-Vjtgq?1jb9J89cYmv9V2&TN zfa^3y-PeEvdz*oJC&-nW&j&j{EmcsaGeM0A$Kg=0SmG_QKH{MV*EFCKIIkx*wx@q5 z+X2RQrYDPo7JO+e3}Bsf8b}FX`E~|=xo-NP{LYmiyou%9*>XQCw;sPut^c72eKY@> zTXYelt7M{!Ya0ldzJxIn1H1DWIZ^*~{H!83X}@kgmtK`i%>BCi;NRDFY>%NZ7sauS z_6ZR~=9eG%t0heI8GuJ$wXXF6NVekM{TDG1VinXA_Qg05Cldl&ah;8}kD|Y2qiu-; zaRwpIMlF5gIJWI&Eyp_$g@kan;^qVSEB^#S*^0Y}SN~xvt}u}NYm#p_efu=j0Li@cIuN1*QHTai1U8%j1DS-+ zxeHsg2ctcv^%FAU5Ssj1<=R=u_?*m4AW8FquS$!0f*coPN~Cg^sEK7)R^3YhNn}Jd1ds6G2QYWiZGYy;BD{A3~2uRn7%G zc?LPh(%UX)#@qC8xfJm-QWWg%!YHvEEgQVB@Gepn}`sb3{##0XwzC6 zJzf~D`4wyAtvXqaiJEgqm9Jql?X@$+Udma;D%hEoA5K|uw) zTr)ftQTs|e5H8;qu)gJ)GdysHXU&vyv$fILz`*G3GGUn-)*s|zFT;xQw`ZyKGk?Kk zhra>rY^9PE)2!>!G^kW|7gTvi+=^+oAL1;t_-`WDdXL|~(O{;7VxJp=_c|lwQ~2?L zaKWad7r31pPrv#+zjbR4 zE4z%O%e+7>_T##m$j6}JTGSQm{%g35wF$n=`691d$46A`;f zn~0JD*B=4!KQQFq*#qQEmpG0>j(8v%?y2q|5)WN*9$%}F7I9}KaPKGXt0WaFb?z2d z)=%_LYy%xJ@Ra_Rr@9Jv@g#{D8b@oi0^@WoZgABjaB?qd>7*=(4OoqYDBp=-sWA^W z8_HuWY{XM!K|CLpaZk#wf%UFi?dkx^zD5KkaPoPcP=l0lyzA(PyiGA0@?-XJ!K6|X z4#PDtc1U1!6XQJ+@sWKy&2@%CZ$;d<7-vbu6_Plep-?wNa5W%VM^k5$Z{0{;+v4gI+lcVkIHp6kAsq>K*_YEVB+!?_n(&8+73?YXi0$tV@YT4`vJk z?9|cdez=X&wZ|aax*I!dnOX#2k9Bgq(`{A{9trjha)4Px7Qv zja3LEHFPneJod~DB44nqi(0YlpP zo*RN4!RHB4NLE^HuO{PZ%54fBfp+z9=pdH|k}Gp15R$qRIK_T~oV-LSfX-(~2e*&% z7M8Y5KJlyqh}Jn@-8Y>bg@cPF8BtwqKwyJ-VtTIoD-0<;rddtLzM9# z!6mZ!GH}7AdPOiL{Nz0(gUa|ZEi9vMQ-!IF@4_>ko_AmuAB#6kHk{N6-Elw*TP4{r zgGodoDCdQ>6Z7mU9?fBq980`*6~qt zp?g>e+ZLn{jc`@y*qtooPZYX8xzK|w^fST~v}a(=vzpbv(FR$9^QIDoE=ex*Bn!=# zLMm@Yl`GxDnzsHDCoea-&@k`q`Vrh&Nei5DL*dsYfA(3d=r= z*RYttF3q*M1cpDA6)Zstj`v6OhmM4kSC1!yE+8o8CEx=c`~Bfkc5%>?h+H?y{z%K) zuw4RLAU5W0si;IWp~&x0Y1AwNE}ShAeVyo1<^joUlL*B;%;0+3WBEf^p3-5|tkmVN zlk!bxKB(hVZIZtued^_q^q%!IYT&&40{DS>_gS>xQ~fA!m`t!7dwvqj!$mW&#;*z3 zMP_u%K)vQhevCVL=4~Uju`isNw>1#M2aH_a3=fsutK39+*jyf}Ihx)O9`XqWXr{!( zexMCg@^(a|lJfFO@f1^X8>kn^JE!E&u%xev{*y$Xh3PwO&4K1QvUj~F{!TI8iJCdJ z<>{%-$L-)W;bPvQJBZjb1Dj*A@;^p$h0aUlGOH08&?4sT1_%0QKxSSqQB#jGmgjl!i*VnJU#bte90 zP{SZ#Epo#&t_@mpZUVYM1SgGg$FFJK5I0rng2~z zlw@8>R@BvZpsb$YF%LP%nsGme46#x*#ON!=JRwFfH34NH09^vA9%51!3~g|}=|H3P zownPO(Uio-KxavlGiO>{rfGD9ha5Ubo8>WDgC0>*$L&H9w*^HaQJc^0Iq$Pqp?h%z z6{bF{`Ao(>93!wsmQ_3T`NCG6A}AiB4!g-Ij6F5Z&THh z%F&nMrzsOtwcm#rSQuwNL@61n{Txlg4-5^8Ni+DO3)If$ODQIsMGWOof>bHof>)G( zc#sRY^V_It&k}E_$Mg7DDbyP=EVMNhQ7@n7OXa|PA};67=tR76;#1rglI7gsHy*F* zEZgUX#`C=*<8mKF7SIIL4q4tZ9KyulOKCYe4|}S{vS2UkFa8vlz@ox$Irlo^7bjQp zr)R+WlfT%4F_MQ!eTb!C&OG2n!S6_%SRlvU)YY?POMI-x{m$R02L3m6nwUHXV4sNp z`7&R`O`f91a4RNH=zE$xKsXr}*y~g#ryO0&nqawFu2C$fb|n0hwobU{GQkw%j)d0q zKU;8=(&Rb)II?n$ef^E9FpnMTBF`kD0$SFDO_E_T<`XREk!W9H$|>-&eJ8Q!>ejG* z8;_CptwDTGH|uV41XDsvBmJ98+RKy&fg}(f|3n~s z^=!LvVtg(hjAr~zSG4XM@I=@Xt?R;JGgXO3g)3lv*Vuu*@clSxAsZ4ZgqMP%i%?Ya zbRBtGjiQ+oU!Wf__d)1rQpc@n*?7&zK2PWfw8lAQA}VJq6uMpq5j?kKc#d^Jj0J71CFe^sd2L@T&*>4HMl3v4J5#6x^B_(IU$tY&jwIS*= zK%&M891Fh9I0yqMtZhy%2#~f>Wez#}Mf-B8@M)Z~Z1?;Rz_Lbqm|} z;UQ?7!r@D_?am|9$>X^N*rDKlpo)Bla$IW967L^Qy*SbZ;}f_}NZ>jGxY9aP+MbeX z0rYy6hFeo{7N0t`0tXgF&ytq8H^WiV8t=<}NGv-J+UP-8tJHY(Uy;r*9k-IiIPYs* zV9m7PAGiR$>d3mMv{;~=;1XRI0WKsl_NU#OoWxjwWCNh~gnm7Oj9p{T8Y{d5kf-`< zdB&~EmUl8NJJ6L$4x3>~RF6O|re1)&v<2Oz%Lal)l%su};R!RG7W4l0jp!-zlf$b^ z0{9~K?^-~j#mmrx%s$lm*GK&;em~{HkGZ2WfUcvA$kWU9Qy-pAA~n?2O|le^$ACca zGjo=r($yR?(A5*6PlA1wo^Ehdn9|er9N6Jt160^L`{D6yH3h>HqR(K|jYR{b;nDq_ z(27FW450Fals`MPsgm@Bo>#L06y-Lj7NsaRqKa)wQQC1u3E~c-DD@!DG3suK*FOdI zXV&zv%0#2n7my){@T};0Pv}t)fEy>ir_An5TzJWkze)Ln}rwz+N@(o zMG@SJAr*k?VeF`&A1>l!?-)ooJH&Ez5L`0$4B&zxHCQku45|4PR7y`N;xZh1$6c)@ z3WgLmjN_RY55I!@6=NYzH*duSqL;80g41H&cDU7Aj>GOVILHfn$gq1_c)2V3FeWS> zlcXJVE>+;1vfENLfI5t#Xw1conkU)l4^%lk-tby53 zL*u^&j|x}llOPM->%jz1H7zUf1>Z9OsF;>YA9<=r)TRn6g}z1JA(?(E&sF zbpiN(-06jr9k>l7eFHWC%FFP{1loUG_$|*2W0ExpmYA7ek0skI?|YjLI!$~f3w5eT z--n!HiG8a)YT%M(v3>j$ioXgA-HrFDLdTY%IdW7He*YpJ@U>yEqPddMhnI4E0}$?x zd7pwTRPDuBqG=Scg40;d1nz7e#7^`h1C%#Fr58+l#k}XD3|`LoQ3T2Xk9J|UsP$Kx zA`)qFpA1h!PuT~MPT&d2>b2#%gsujw;_fw>s0#YyQB+pUlTSQ@=Q4_%hWYy2y>);wBYSg5=pBz$Me=eqp)sCrip;7<%IjVWUB|@k|Ds z>$;IZVp!(rxBd8bG8zK1KSyj?3)SnWTRh)vJ_9SX=ew^F!X&&bT}}=^PL9-;`zRgg4*-#^Ciea5H8*Go!Z3nm5smR`KE6Cbv$2~ z7lp2_V2&qLO)V*&?_S5&Q5F?C0Q;7v?1e>@WgBCh2@PN1P)#|o9}-nJ415t5MOWbD zmzZ}NI}dzFc)vf6l2(fMd$#fzKSEK>*HZHJ0UjDt==u$1Jt1x&H*q{s6UWsPlJq2T zUUM8el}(lnB6E~Y);VsIVIDb%O_mhc=p!vCkGCKjWE{ja!zvneaI*H+rrGoCALuHC z4td67bSC*JrrFC_Gt?8Fm}a!8KmI%3^093Bqev8Bm2nF#FUdliObczFSZL@AC^Y+& zcsGcJJ}H51BC+jY+Chp@B^oHzE2gn*?Y0*n(r4|}UNA?2wO730N+SCl=jde6sz{_^ zGzqC&Xtong`g2Q0XRm6#BQ?SHy1(xPYPub#ONKEMwNgYWv_8!|tA!2s(nObtQW zj!*wZwIoF8;#H)qe+`w&m%VyBV1c0(J&s>r8 zLfM#Dq*fNkTCp()V5agO0&am}q^!y$H18A5nS#a#<)A|!oL{f|9eg-j8gMQf za4LYHCfWfCaVo>}=&~l}Ip>DzivXVJ!w1$R_hJ0&X7kp>)impAmZ-;MJxgRdl=VXl zflV-HGs!=2XtRMkY5M~Tt$mPsiLC@gOx?*%N>6tpA-3VtNvA@yk#Bq~35 zb;ioCO|HDRRDKhY;Yce~E-o@?cyeXN!l$5ck|8&7HwaQVZYGZNG7=<#|AslqygVmS zu!04*W2Q;#0uhoQpb-*nx_(tgvL0R)Co5;cInt&(iM9mvB%=OHS7anc zkxvpi94plAdKIt5qVpDf+%n6y$2Doy$G@Oes?gIcG)bmHNiow5lDG(j4pT`375xa? z`wx-4oCSTPve#JdSCqq^c+QNLyM%_9vg(e&ii*VLU!z?H!%4^GpTw=ipmJqo5bax;V_2g3YC#~_>?WtH;_h&%l8(NTr#AQ+|_hcQq;sUc*@%M?()qkf<~d3zIGQ0J}mF?k+{j z^D=rv@YoQU_65RIdfJZ-i*x)iqwXVet0fqRs+FpvY2XQ+&qpfE9OY1kVH#w0LA6=l zOkOm+!Xd##m1b#Vm?8l;IF>r8{$kWWNH)!L{m_p+!&pBo!v~D4l}X1d=@~wB1AIZF zZYAhzyjG>{RD4W6Zlm;K*Ze1ZQ$~(qtL+5Fs;P-aAa;#PnbsL=<_`y!V5bb0c%h=o z!jqTy^g~!*tL^;>MqGfX3eYVmLQB#2{eEsCU7G$;JEovi&*JPa$uuZLU+)p9H)mdTI;BO_BEO9`pK zSv2;u4-*XSVb&Rs4$6oNhijP`Uu=TWe3!gN_AKz0r~^cJ+MA>j!9a+33haF-vW-9;l>5*Sjhhv zqG}_P317+$VE<0Id}BWLBurR`qh`2uA%7EBUf6qJ8M3xxJko47g-lG^@LT$vGZ^d0 zbHf@n$3iE3QfcP)7Fo3yf_kI&Vyyf{kA!!~$|O@`SIqk^7JVJqs|gzr*vkpKlYSuU z)2nDjz*{jM1HNV%F2+!kELZ2bVMOA~W<&AVnOsqIN1`hebT<**bK0#mt!djd<&Z6? zL**!U|FJO+e>35Ek_0o<*z#Fws~U*O^BgM#k2P_QI*6y|=xk*Z@9|`_aGxi_#B8pw znN}ZUabTe9gXdyErY;-L7Qp8PaPod6!DWPMi)O~wIo`#>Y@)>hLI2J$DzG1DBNku~ z>XhZCWeoA%05VG%0l<`^lIgpg#o)lJ_tA<>>#`hZGS)A)>mjCvjB{quIbTOxXmnDER9 z0jEy6wcIVfAYY}o=V1Pq-j2aONb2ofxOIAajHG@Pl);WWcyHgcSaDtVb}_mZy?q7Z z6;5w=0gI)#TPj4Vw{O!@V!6g|Abv4Lj-*u*?s9|BZ=WBvUMr}s`y?mev5Ag0c5A(wHh8p1Ct?binp+ulYT=7W6{ z`2H4ql46l*=3rl4FQ#|XEtU`mr<0g1`EwH&OzK(>Gb$gd=TeZ#-a(Qxs)3e>Zj>*) z@O{kNXOVhaBX8F;^EYJCq~*(N@lssrB)UtVcn81{c0}S(G(tq; z7mP|EQX(-%ixT#Yf-Wr*ud=Femq9{P6Oq_Yyc7xa6`9~jF#qUoo+!|% zC%3qV!7Ys|=O}KZZ)P-A&bKEi=l2llMc+KTOjvr5zS&r-c%=JgCTPHL{U_oNPT$;E zr~788LZtepLHDWUs{J(HHy48{^v!Qgl(P)iE7+Cnn`%s`?3;!XRj=+Fri5d-4n|#x zzWLt|*FOWqmKd%-sct%WkL=+5mC_?JBAw1?03{rea|Mu_i8yzMjJ;e6bPQuPRJ-FD z%F0lksf#s}_HZD3@D?8zPK|HGyyUAgH#{Nr@sRE>euu!(CaC|~OHkgZy#YB~Q5)h= z%UF$3yNz}Q{r%cOa{n3cxs;s0Nk3W2Ck*=44ikv;h@o}jz7OyJK$}oPLG<7gdik|O zr9>|8*C+0eRd2?MY&n+`*-{#Foee*1D27*rYZWeE`wAqP*hn}f^UB%CaivVK^Y-hK;o_)qu z*-sZDel`ODV!-8ZGHUNbaoIrI{oHTG2~r!nqqn1C^qgY}f=a~bTGYTW<3j6R`D&2# z?9U5OZ{c1~=tqDAA_1NYwGqjU4A=mJ4h@NUPedEZhtc#WYo~z8jT2IX8gvkQrlZO{F0f&FHrhrn ztCxJT3&z@XayQ~_4qYwVPLBW=$j)0)ov;%&y$CA|<{!2ZD078)oS{i+qaveoM>`Mh zTGP3;iRTkPEe~cg*Gmx@DyJgTEeg;GLZjrHQVPQ0WTjUHeDRQs&A&RL@6gY^EQq69)_gW;-kFQN;$S-DfciKqb}nq6gNBI^If;kBTsGSyTA^TV-xiGu6<#e$l3=#5cKwZfWg%%7J~^A`T)D6 z>G`h5y`NNIG7E@Ik#p>OOPs<=S#|K@zxVaAZe@vbd#kdc`$C(-KTT?2)#)*ucCWvUZi zm*8_d+i=7NzPPiIC#Lg*I`|L|4|~N2c;sU{V|b3h=h8IKBa4Ax!}~3GFe(~H$l?&(yy{V&Cc*?*u@ICY?cfA#C*^FSqwN&VJ?U6tny%t-&gXeOKV+#== z@dODtHvxDg0nY`XEa|m?f)BP!+A;+<3)=W=7!I;Z$e392t^neG6-2Ta5no2c{JOPK zcM1{z0Jj$|-?)Wz`Swc80rI5M5Ytxcmc7S5jK`8a#C4tEVmfs60m0>Z4cz%}H-;^f z;|$i?ffAI3K10Mh!xxL!*r&p7#XFu|gf(V1=w4)qXd+5T#2)bsn+CAbbw73yilYfH z;azl?!<`}`yIxu}h{zVx%@r>dxfa5mJnpw}J{0t|*!JQiu7n>ZQRc;qAaR)K^zP+< z;kI!MM#SO|aluo*KEy?Q_wp?A%5py{h<1s?8Ft-CpDtWbDVX%`; ze6O^hJ4XtS(1jVzT_Uf9qU&Ij2Dv+C8X-YH4~ zaVm!OcO!yVEA8)k3+=PSsevmN3%-laT=*sUe}nLUH2HtBc(Cq0?}5xoAae&U;$)VK zG(zXPh6xsNiw|R%B;0-T5|Xl`B43?KfK7#K?Rr|iP?SEs95MhE1`-us$qMJe9mIFs z$N+E*GUE~7TnUd`_cd?21X3Gf;ntQMvw5yf08kD zPDQ-m+!*J`HLR(V_^ZxZSP1;cu&Q_ra5&*QH1gU6jkGr05o~ZtTo(FZOcjjJ8rBPfclC00F{d#FPqM z7eh!qp&599(61a_EXVuyQ+v6_!K8$#ipg@2I>LAyJYgM>BdOg%s!WbHh_>5h4t9rGsO z*jnu29E&50w_6`c5Cw-U$s~^nM;%HG@^C2e^G#Xz>-spdSBPvho1QjAn(Aq2LhB<+ zv}~~KC7P$VD;p6GQLSg=9fze_!0VcaTUo%1y@`u5sE0kch^q(VT@He65F{z5qGmO4 z!;wn4W3i-C@^tW)x!fkXnX*RRI-6u-!1pVV(voj^AD(@P|DhSae}^2C84$+VuaWb#-`;Zk+u&I698>QHiB5I%RfUGOeyqGX@*4%zz?w(6Zb}r=EBpvpT-B!NHj5e zItFvPe>2R$XFT}ritBT5TwEDM6Q75)_Q@G=#buD_>Juq3_~r@vJeMa?SF~3r!Kq`M z`ufNTXu(S{$z!iGPZ-9J`1PIMQXQ-cJ5G%slHC0@`Y5o8=+ta{8(=_Etkq8Sd~ziQ zBhowc^(44C8qVYx_7ecn;rkhZfv3>#Uvy-kijy1}&oB&Us63zD^$hLE9EZ)4>dO?Q zQmhLojWxs^aY?*mITFEu5;)!G(L+}VUEfhyBi=rI1P~t-Ik*CMf> zGk(c}3@@hBgV@SQE<$pE<4-UC!LIg+XpSD_ISVEOzp-!_``}(|zK3e9d6kD;kl*}p z7oVfH3kPVXO%0Z}97xED$}>qq z1C=35Kba^!nx%OdvA9OEE4mrMV4{m!NnJgnGxXFOzy_F{1yiLp{jqt~3`)1-JMi%*f_?zM3BX?CGF_KhN2Ma*MA@|9%z^3{PUdiui2lWlP; zd(&pWgbVIXdmI<>2>)HA6WSH${{pR(Pt0YZaM6ZZVoK~yJLWAR3a8D>CW0uIr#t^>l43>v=voSC;?6Tp4KQ>@kX7ZSk<#V{ zbPU{1mA697u*VQevNz{DlH&X zfd+7ffphQ6BBMOOx$B0NKz^4<+hUFUMM17V$-7O4P_PYA(K^7+5yW7~0jNjsJSvyW z&Qn)ZqFKOtZe%@NRxuWSq3bDRJ!tG_Gm;wHKLPiphHH_bu^7`FP;12nbAJP0Q4jGO zF&<@zcdh5Zbe#X9j<}T}zHl~&I41SExQK7|c@CYghWMj`OB~qaIkv+^n?zY8hIpaU zJD$+ls2vlf{lY1#Fey4gC~}=f7RzWwhM5dhI83*}Vd8hHoWn09bPq+H_cTOws@iP78#uo?#dDboi~#`qRw*1x$?2Mm`FL=NZ7~3EiJ*cn0Cp z%g`J;8`Zq#RO1ZHpq#Mr-wjJmz&;XiEC@JAsCswf6gB=jyhtwU@uwsu#QEfv5q$!v(lV+t3_s&;Es;3l ztn1tcExGx7jD;Se84on+qYuk&ToSe17b9w{rLh6Q1(C)N;BPq6h~su%!>vf;+Go{- z(`6Yh;{HA7&iL1rD@rMJ~!hEB%dqPx@~PYMIZQyr3L zYOEeEQ(DGA$L-H+0j}q%d0iJHM`Zzvvc<=;#r%}AcDu$4Y<#wQ%z-r)9!E%n+f;C1 z2+jeQ{&b=zUB@Q?Pb6R-0BL0vbF#6#@1y-O@7@>0xTI}Slz`78yp6D{oBWo zWli9m1n|iOUI5_K9{Qg;UR)C>1n~(^B3D&5P>!&|SlEMzd0c5G1&%@xO;6}W2@anx zUoS__4JV3dPqb9y=t3M%NlUtpTo%`e+q9-TSxURx&5aAtJy1cigK-1QcM1?AhfrS2 zaT{$Tz3Xm#8rOfys4m)y>-avX73eB5$#T{Ii;qQ&3V;!ZZBf@ z1Z{3DCjw9XLNG}&lCC{rO=h7OTiZIVup1~Zg~;O#yNWs3^u<#xNIye z#S4Ln4v;waTKm|p(p0u6MDI*vAYk+q!W6nFkDk!esKuYYf3eyj8K+9D1IZf|$)p#S z3FwuhE0Pr;T6~Z_jM_%0TvjfLH)b?RF&Pt1_CLWj6`-B% zt-k=#arT2cg|v6m4!k7+{{Z>jMMCM`kDg=<3MM3CP%+^N7pA(FB%o&!8hhj!s#2QC zUUo7mjH};H3E+naj9^-t|CZX7>}m|7PK5IQknttOMYC62LPEJRHDyJb{nZpq|9X#l&H`PyR=|x7R=)NpJsgJSZBf02Kp?7@*(XZ%W<3o`MD_kvqI7RJY$Js3m9x?$zAlSAsk&Efebn*w-H@T+ z6a!Js$WWV_s}yQi_8v^xCZYAK?LauV%Wi+7qh36rRUpAwxCni+Uk|sI6otbzg|d;I`ZXNHD#HlpkTcP-vPmKJkTb{kTM?&yJ{mxdAq%6a8sY%JmKEoq z9%oS?dN+v?jr+tCXfQm|JiS!YUN`I$Ag6NUv6n;*m5Z~`u&GelplFFYC9^DCvD61< zLGv!{Y#$$IFw9S~)mXTh96AD*>B%H?NmFeT=mgBd_J@<4?NAP$Z-{3N=uXwwaEN3l zR2NbTv!f?$s^g!dL}s-3?s=S|FKQ&)ShyWn8*hc3P)R;e4l(;926n4BEawH(=anI< zi1~6uN0P%*#*{Jy%GcUQqt)azoW9_ZvdLOsnh9tog( z=^fAmIu_TEIn0Mj%RZ$ek}C@Jn4~7Q)A538*l{R-my}mA?v64Qpvp3Swo(PU#nmzp zy2riGZh57u&BvV?^sUn>W!T#XE(MT$!+?c9Ry5Y!ic3Y^0HA*Jd;t!Y{q5&>F5#L_%2;$L~0c}cr`*=d)ycM8Ee7ggS z0~O=jo%tr>I>f==G`@WY@r?sM#JAfpJ1OG+0~3icFM_VL-@5$&+xWK0?}6ZRDzc|$ z2v#}}t8@0$$c`F*1cbY4xSwWE00%-(!^kSNe&mvAPs94!u<*39!LSY(*3OuB7O2N0 z6NFD+H0VQ+T}uzvsF_K=qcg#TYC)kl#^gdoDz3u}^Wwv}D2FNOU%nhu5t0lIJkgq) z*qRHrrv%&c#8x5`elcwAY1=>(5zDd>YCi?=pUz|L3jRgHV`Wh`#o*IB4lKUqz+pEH z#r=^oa6zIEpYS)Y@eui54z&pzbT$btE1Z(!iEL1F;&o_h5cBAfjPCm`u#Wx-lwmfJun-A!&4nZNi09gB7mHD@G&<|B%Lt|f%)lW(eIt{p_NYX`y|u4)$@3! zjTJ1z{(&G@^d+|0a$hJ;U{T;@*ASsf44&yvaa47=1w=4`0SDo>V94T6)$^VZ7cppET+vBa ziY*aLInic!bD@Qkl&6}zOA`k6M$n+#EKjuuZ`-i122r)r_ny6W((y~PDs}ec+PKhA85$m z;lO;sM?W@sw4RSXOL}DOH)_`LVJ#k_p-$N~eD(sK#k`lXD_8Fu zSrLqRkHo`tJBB;Ewlej!m{TmQhjCarz*RYORhjjXacZaMF`{Y2zR4U_wPY+NrH`E9 zSqn08=8SFa<$lYe&hH(3t7uY!s*?tj+4at3ad3$?{g85X&N%gSskIDwh_-nt70(!T z&baE+=svwA@u2$=sXNUi-D&+4SD%S*DB&wfrPjak%_PIx8uLzgK)Qt9dqM78?BIKu zLQz+IEIJLzoS?y$kMS0|4geA#fGKoMxgQsoA=5>l+Zgj6g(o_bfp|9m3wU_Yhfz0( zcIqsvJ-zd^raRN@Tq*kot@^ygO$Iyr* zE>IYRM!ZyM#Ni;58nL+?R+Bj0kQ%YiFYtBzv1N@o0yb$^;69KFjd-wKfm%dAQ4;kKiXsAO56z7Y;R=NK^TucDhpN!(Taa zEZ5hh1N(u*GIw?ZA(LfN4z!x&oo-FZ2rEO9l0-A@yN*Oz@qyAd_BlF@^G26f{>CPvAxu?#22k zGO$I=I~Qw;I%JN4Rj}nBEwUEwAb(%wki-D3y;DTZdqac*i!*1_l8!F|3OyJOUHA*j z{vZ+yVJSqc07JR}Q#?KuKeNtJ|!sL-XR2L(wlqb4ALZ39J(;ZD)tD6 zWc_>;>JOeOQJJl&1H$SDzL!|_i|pn`)wbe_KxFux3}ShG!oao3En+KwVMQseTna-j z<~=RJ@uwCx^U+PW8mhi&jokpj*7JpXhga=uKA&wygFpWevEi%}78P!|_4rZ@7FXov z%Er#viWzLJSbcca-sZv}#hrdRCHQo9Ref`RcywM_i{)@4IQ-Vwr=8BGi`qM3;UTCO z67weVZ&G84RAWOL`=&ldlEV*>BLDJ5w9nDPv+toyt&Dlkf|TgM1JVQwh6Crq!-+pd zVmM+j0V9xe7!1s8Sc!%>?;IU(Kwld3-a>a<>+Pk3#mzw`mD+j}H{__E`AG;2^KvBX z_~hG$BQGDF?BAw*|5KTeu1kLhjZE56{s-)gUiWab$`1JU*W8Wp*6@0M`_nTVTl^)D zco#nyIo7oPYo06hi9_PC3T)$Z|^Ad{{m-Cj?%oJ=O40&RPD63|=? zG)REX6bifptCAod(hwsA;yW4Q-j}PBASP&tay2~kXGbmXu4HO1)Iea2vbTA%j9Jy# z5<=s-pQ{~ar2C0jFvnL%o8Q?R2fE|MRG=(54QhIg>3nju1@S`!3|VgQx`#QP-n} z`9Zd`r2^+VHpqHGfq%!&iFogGzzYd}Gr_r$64=`*@QDh%kHS960Y9AJ;|czX0{<=~ z*h>`n+mxV)m+ck~ZK(qIbpTI%2K9U<^A#|FV!2;YgAT2;IO+60U^UDf^1r*z#{5HoH+}UJ>7;P)%9;ecc24YZ%Plrrm36~;BUxqKKmf{-wpG1@J&mjI8 z!9QjoeDxe&OyHlfxSNOnkp(h_>FHO`!2i4O|AYAd3H(1B|JURH*YJM>f%5pLC%!KX zF6pQVwh9!idKK|}F6J7wo4~s0_vcY4Tvy-ue<*wR0IR3{|3B5PT*e-;3B{l?E-5l8 zBihx}9%qJJazZigIdX&zJh#K7&|! z{kNj&bXr-A`MA_a(<(H#9*)v;W|`t5GA0#-CDexY>IN3xcxBtD1D30>NQq`i`A9f6 zfWyx#oT5qr!`bxn3JZ>>N=KUUWCBb--cO^Rw?=&+(0WqOSaMn&r^}qUUB>9^4B1mf0u=(JFsns1^TGDRrjbiUBG$fl`I7sHyCC2+hx9 z7n^N(z3D3B7{B`3FP~%PS^XPs8pneEI8^vguPo9ZV$^@O@g3&QQDfO6o}IA z1o^dv0u5ObUWRU5v2n}Q%)z0RZVNDsjw5oBjSG&rI%*Y zL^s@~Ayvks`|r&12vPbgkH(|_Tmc{6?&$Mq9#8P-G65$e!zt{28TMQ2MCq=3pl5lO zM`wzj81&?e(q~uZiPA)s%4x;fD%HJ6E0B~gU~e9~oG3j4M%(b(Z`~C+gU>|iT#Dq0 z(q!S^X-JX&5Sz}ih)?KVDHX@2iJ0leruTE$#Kk#l0yce(!uB5D!e`S5Ji(^N9h>%} zu(x#EJW;yzZ#4MDESsi@pgkZcUz8TolmbzjA;|HAi;#}ktU*}vc*DCt8#|wfmH;z)+(cr6XYiRQ z)#F^}Xr;4wG&Zdio6bphbQ4^QW7B8>CnFOn>|L=lrEi;!x$5#5bzmMnsZmaC_S&5hEr2vCj{PU z5LSa{jXQNSp7ll~e4gEi9cw(B=SMAlqu^E^jc3#A;mg3yKF==V3DLSjz{$w*6!u2r z?jR)cN6Tax$QV&xNb}1uF50q2^lc4&{tC<7OEb(8_&!;C}Dm);hR~se)Ub5BIa+`a8H*2lqpR;2y|_>%1p$T^*d~;D%bg)AHd;1o!?x zwSGK|WK|j)kYHS_vzl)ap;DivI|}sQ0xgVS5WJA3U6#9WWR@_aPsvw-F|6DKOuUts z&=-}@hZ_fN0W$IxA<13AVi{r+^x3&Z7M4+e?R-b3XDdaogf}I zzqJE`kml?v`Q-H%(6AQj%N~+mKVEHJR;9Dq?X6k$mMT)uadIo%XZW0JY?9&g*U32yV?szr`cNXnumyyqe1_ee zsp@p9Y8TNc9N9YEalalmR`voTF?D2k$oU#8x~H~jVK}}GpXvSMRma;VruR@sYLZ&w z7N{b1lf`_B7Tw3S=z=_X-&%;)8KM>;+RG4ymMA#pI`Bj!*E(=INxVS^V%}fKqjliC zi|C}+e(*c+HlFCf;{=?H^rW!&86J`^@6rx)Zpl=+P*q;k57ziAhBZ)!N+5bsabXs0 z5nyyesuz&xTO=77E@Yl@ml-Q}mb9r#gmpMabTuM@^|c zZkoT#rujLP@@aaPtPQ`!D?Ux}{Y~O;CZJWD_(3*Q%xd+ymq2+L_YP&`XSp|YKOT*H ze?Ucfw-DtwZ84rFxK|?JWaKFMmk;7Np<9*xD56gi3GW)w>y3M^{_UyXuW~R}u~qq~ zbWV1}&E?UmJO=^s_6({#kteFWTENN3&sa*{Agc67oT~in=1i6EsmkZ~Q)JM9dnh4E5CzZBmA=rv9-5lr22c-TTb!Sk8UNF^*FQ6PF_o_J;k`(GNem zoYvB4%Qui_RHk;?mo^q#Yn9fs>8YKC7H;~2ntc;3^{z~Z%FuTRPs2DhfTZS`A0%h| zG@TC(ql~~N?(4MshOqU5BL6%N6yP&}iFH{P(Ih+ss|%Ls<%v1?V+dnV7ls7WLaNL^snMRw%q zSsRJHdQ-?db!!_5h;#$%Su4D0+2`HCG%Sm0_W+Z$#%CCL?Nl$5RI9wl_|)nCu!#mE zb@t`iVZ$=s3?6OR3_gdU(YC=Ksr&N8usK7($w+67)by_%gORG1&7V!n-nW+RAJCJ! z1!8iIa?(8a0ztA%jYA@6^^5%ZYlYF@(rskyu0{>h? zAMarBxrnL6*c`K)s0BT6JDu&eR+_=EWTLNOweaC&n%k$StjgD0ty@E#E0%uK z#=Bc<&)moAE}96uv~Z)cVkj1E>BtYgmJ1qgyvw}?M`C$2dBPUnre8WrC^YPUWl7X0 z=WinCVaO>o^DI%%w>6w2vbrl{fcy;{5VCNr>GFP2-xD<-+KN+|_dKJ+c_m@DYL%$C zUe$eOQv0;3n?iM*Q&dW^|Yr z_!oYn3>2Tv5V2KzB+WvWOxIb7iO@YrDEE<=#P zg1gb_)*zBTb~S>+ah+fcn-5mGudUo>l~b#-v-9C+s$jcC$p_BJDWIB|KgF7Rgx!8*DtLr;S!s|9s#&{c$#hBoR#6so__UL7pq<#@mXx-&T@Xq=|wr;kNT`- zIpTj|wvv6s{x~&Ywd{LIhW&R37R#S-5p&poDUZhf&1b>lA><30Z?S8qGnKv+l<}w1ety9VDJYAvEN|XahxqfR zY<8w*E$mnJJD6dc8=#<1c)RhmphJ4wuiOrKoX)Zi2?Sw)U-5+9iU@*yz@`qlJ+TV| zy2u!~w=UBV(eLDsoayD7G~kbhT+f#1Nl|wY`3Wh!eV5FYZ9ekwePD zO{A6Nh{xaSiW0T05oJnEMEzbwm2{M1+z*2#bpb6#GD`7Q{ejuQ5VL_My(sVF*)hzccW8yZO|h-}kp)x&8h$l3@KFF&3CGMOzM39cT0`&h(}oQDQLY zYaDx@L7gZ04CTUkmXV4QGw#m?&e1$>Fn0mbK+*igh2-Zs$ zH)a?#ShU;;Ey1{v1)7d*M^pUxT^{L&3Va?X#I@62MCp3c+Fbtd>Vs2^Is6LSFP}NK z&U7c8V9b%249JpnnCkd}Itsg>P(ey#HRp|!?xz$L$txyg=2_LXWM-!M!&TRMwI}hG z@9FFYS$<-ufd85W9x31pt?}A^o7D*zWy7r0YZiZRgb#(w0AQ-kVyYIVv(&^ysLO?! zj=nhP=AnB^F&8~;zq(C3VZwD@#Tz!cdn+T+uGn8t17=` z!u6YZ&G}L;IgU}l;D5pBmqw-0(_Hz7dT*lIqj=)0v=EV_;vv&0Jbv^-a^Q|pP0`yR}vap z*buR<@R@O+fKO3?)K*Ngmsv>4(JZ<0WrK}bCO29r-?tpWyYysGqcXIP zz703(%quf=I}1cH7e8hqe}Cb0Uotf9l}B4%6giI?Ir#_t`{sbCE;pxcPAfw${hE`9 zaN|=p09X0`9Iu_@c2DpcF#+1?5;At(YrSy(T>01L&*ib^HPNCA?+bT2=Q(m+{;P)L z!4bsNL8tQIEU3u}ledM914Wp^O+$`j;8^?Sm7k zBpG@I@7;IbPMs9EZ-1Z6s0h~2)&Q8>z3WuP(c4JYM>yy00$Z`0Z3rVnD4XNF-Nf7M zirpkv>3FNue6`Q{i7p?QTjME$N>u!KRenc4YHiz*ij(I#rwt#ijBPajvK{Ulmdw=5 zvYmFjYs33~?9=<3JhV)NAa&DkIc!`1D1ETlyZx&?hi#Hb>0uoHQB*WSMV`ZEqMz!u ztuhqTktQ{OVIeJhpo)G&M@3sk%XFz$QAD;51^Edxm_HN#mr-q|!fCSWGc)1PV|g?M z`69~4`~F>DK{oS*f;?Ejtj|!`>(-VrB318GQ>ph`tM@q7`$~j*6QPT;RbGI0wJN_N zj+3pj-}^jTmDisD+8IHW(|MxG=LMXM97JL7me2Dh-%;5r$EwOQS7jQ1!*At!j9#nq zcX_6A$zg%1e4M6%ZG$SS+%&M8GnMb=kGH2)xx9wt{Qm1{@yqIF5f{D zpW;9z(bbkN$Z=CK_MmqVZ*l#uG7j(fBe&lDX{kx1;e+XK5No zXZ{sw3^&a{Kj}`<vH2x|_-;{j%CL3W>NgjS;I;Fg_)^_ww z5q+0*|G(2W3xs~pwOz?osf6*Xk9YmV474Vf2h&wYcfXEI7{3gXInWLgO~H}`u&4)9 z90>r6%Dgw*b21?;E4NdvOit~5vb?Dg@nvR&WuGECEJn<#Kbwcsps#*HY}sP%&e0?v zpU{nc%*SQym`L+?aNTCLXv(XLo2762$iTT)?>i%H984DSvI_-FiDIeF8f- zs>&2>tm9C77K6ras^Q*Q(%T0M$C0R%(U7N0Chc;`vKS$$Bw;UJK|~eMhpjbD%+00~ zy0HO3-#^CP;=?;RAKVuDV3K_xBo@_fAdpG14eig>pxy_hiQMAoHmCY}Wni9O8QMG0 zE9<1n{VVGu+sV%6(h1^4LHcm~R_@q*>Y|#~KcHpf4x` z;DbBOG8^U}f2=I2Pw5oC&AMO3;GiGS*J|?ZM+@KuAArSn*il93Uf;rIhCS$it9IX7 z-M4jPR4(a%>*c0IrTTE=LK|0jTW0_xtyks@v~Z)2{x7r(eavz? z<7W|cH9L%M?}0HTjp=qih8s7VHsL0%Dy1aJ_Tnq!bglJ3YxXO3bV!fw5eSpA#$gd} zu+5&P;T^mL-L0;LH}wHuP4ZG_bHoy-G90E6D6UNms!p83 z7`+OUV~`Gm(!mfI9Qh|0u}_ih91XKw{I}f|npJa%**i9}LKL4chsLxAn(IgOX{~_f z76Wpt055(mO|Xo9^xmYAfq8n2HI!^4`caxd0Uu>BDdA|xuT*5QcYhB2c17Uru%KU@ zE=a8M_TDy~wtFGpu--;fBv32~DG1KWNxjPnV^C3K?yQ}~I+F$#3!OsHv?B~|?jSD9 z7LT@E%>qQ~E=Fk{yKM99ZS9~1hip!c5#>G^y;OX8v}7wCC{o`1FHGxc1n=U?pkL_H7X=T*u| zn+0MjJCMq9?BHv&)%6s(&VLM6Fix-%p;6H7=dr!6CL|-hatV$VU|0#)eS)_W#%J`r z(Fp3M=LfUT>E1lwntk4==Xmz{OFdtfeg2r|wn;v+5A|@WU(*|UsP!LK=%ErlHwJ2@ z1WV1zj`W4|l2Z=b0(5BJohji5=yGVh zS(T2qO7jCfj8p|@b#}ROHyaLQb1{a^z*n`S_+oY~r6n8RKLQ{JVl5C#tj~c~EUmi@RpAek!Pg3@UO{Omwk22fzCk z!RQILOObY34X?wQ3{SgdYxq{B)^rgaky$m_8kQW{p62fbd!JwnIB9HzotjjX2e5gI z@OAg2aWvi3xg@=3Os4)~bcf?{J~nTirD7|&?ni<-9T^dWP-i`umA`%SuE0fGI`6F* z*Dt9(jMkvDdLgvg&Z-Zt9p5}U)7qeX7r*?+A@$KDCbI>yH!K+U7U$Gct>3SuevREI zk$M8~qH4f2q~>f(J+MWZp*O&^_PXF0P&-{P4YKleK?x;H7X+1VtxAVkrA5`i&z;p( zLG%BDq!np?dQ?thdK&w76kg8?hq|4d(YdvxmYB}%IW|w{mhfmgcm0v*)tz4Ub?z#j z(79h94{$P4N?~umcYF<$#wm4m^-x_`Qdf?;MQ9IHr{wf(0KSXBnML3;O%CUVxOJ)% zFX{J&aF)}uj>=<|k+SM`?B?xDhzmvOvYST7OQMC6iD`DIQiC{xEIls zvCCOA`WE)P)pZkHauitF<^AK}b&I;KBLnfYyB?V#|412IYA58Dk2&aLU}Y9y-O6(>_Mi!CcV62Ij*2$7b|46k5QgFa6&zUKgd^qBw`b z86%S;I&qw9P5jweydmOJ6Mw|MX=Zt14)1E>Pt4_yci>vbsWUfm zwD!<=w~rz#FOG7NRXv|_`Bl%;8$~J}v2XDw7Vv_47xKq@aaCTu3^P~fm8vsBokb7w zl&*Y$;>q7}O3k(-q!7#!3rb(D(r*Ev(%b?tg$vNI^lF!5TUb_@JL>ucCRg%GyKo=J z3uSmxI+L~B`%AzIdb!~MpPt!ZG?Ni~@r{YHm@Us^8g*pzJlZa9r%g>87fvZfpw3_3 z#WTl5T}q6~H8 zu-!4DF5pevf-c0B30{$-0mx=l^QNJeZ*JS;Q=~qm@#_88M{TicR zWAtl^eoY~>bH4ZPHgFLIGeuDlK612+rLXBEkBN%y9MPs@UG18=06;Bp-&IieN4Q11 zG8cf!kDdL-;c!Kckt=%MDgrsbScu7vKr1}F@i)4yc0n-=wbP5et%1iy`m%Obk++PS zc84NE@9ZL=iCTgOh2#P|x9Ho2Mc>YA|2AKw$Fj!qvRxR>5oO8cj1rwgyX#)+;X8Vl zN`=l?vW9_@dkTl0zoA`GrMhOVESC5w9a%F>Mb>I;bEehMEzjaeyI-U(-UcW3?YyYI zEBkfZBV={Y0UrBytClY10Nv?;ZazE!dV8dRE_Og&TfzXfT|o>7NfnNJhRTls;+O!U zhagU*qN6i7zN{3E{sF`uf;a?-ei?`>4i!X60I{ziB2Uq1-i8H5YpPlX@|q?MI+GU# zI}2;jbIFpGXv*kilJJZDO1l09;GnbT|$_Os`&rr&IS?so&Oz8c z`DHi-h@-7)+AuI8XARTr?jMA-Mr<_2qFQbdPCE!`BCO8&z8f#KoC!yOP;tK-97 zKTD#K99rHV_?bV4rVaKFCpt1Q@`zF}WDX}f+jW>boM>G3aH8_;;Y4R(3y?rjU37oIMPElRCdZ9PV^Bx$UB_qRnd@)+-~78P9)sr zFtO}~)c(fHl1e^f3a_`ZV22ak2xR`@ME(6DKhbVeytP-NT59l zGa#ThyTS)kSbb;bAL~mpG+9n3ugXDV_xsT>2FvBb_h;eTm*U5};y;)HQF4{5`|f}z zM+tTou+a5kov@aClo>$Y^e%-*0$slwF#q#NAa~#2*jRE>@9CTYG~JjT+U-HgX{1y! zl{GDd&YHv{Ys8&2hpb)PZQw@T05~wM^$~`|+M2}Q*XpZHqIPbOU3WfkquM)c;KCZ_ zQ0yFcKVa>wWXw*?g!}Y^Bx;QQBR8AAQ3;z^Z6>Xgs-GBvtjzeklA+kW8 zc~Nrrj`Fz@p^wpS)TA>b70f!S2k+MKE*3|7gpP{xEAxJsp5m;ACQ8mnv3dg#> z@fO>SYaFnsdm@pyTCiZb_YI%7+trYv zW!9e-%jjM%1<47fLwCuReqE(cQ|SbRNp7JUu;7>=kX(m?5R!lABYESL3<+-wNzW`2 z?3Fwu?MyO_R#sGB_DXx&yi(dc#Mr8BDyf+uYB)qo`Hv3~<877-Aim0@*KU$$c{$j9 z(8lqnc5bEBNClev1~hb)aca(9$=APAXMKtK)#=as&@{U|qx=~9CF9Oi?98KGp0Ru& zKXl{ybNt9$GxZOntK?pANiN*w8Sm1cT%PeBQ4m=~oY~x^jT_HLNqEqcO?Oyc)(Y>D zXVn)aXZwY9pur6LWE6#QmF)727NLV8-CM+T_9&0R>13VsdxM0ZbE*#)4dlm+U{$QU z(X|Pw>t@(BXO%pQGs_h&e>8kt&+>O0Q}l0W@gb1Lr3C}maaDsjsb<0=2=EgFv;+R0z(mL4o;t$S_^i&uAP=;8`gKdzYFs=+c#eCj-Ji4$&P&I*W% zKC|6EnD~bx38{bXEIqXqD8+-$1Jk-qV}*C&GveJQEc$R$B}=f#@=@avLzRg>(}Cit z>6FAnn`YEJY)m?;G;vI6V$saj)-8L>N zqxu&)dyj#=aZ$(W#H;mPaUscJ=$Kv;I9$Xh91X_8BPa{ih=%F8JuHUBrc^k-{-g}Y4+M#>RovC^6dWjqkk25X>5n!A zxaTUcHzYI=;j~e=i?n2R)NRe9jk=SD_@nL^eq^Nk;6c&`CH=se9d(}(VPMp)IZT+c zqi&5vTcd7!izTk`4td%}-3Fp*rpg(0n+U=Adf*#gH}qymEY!I1M;!;#KE`9pC6|>< z6;T&6PW8-!PqtuRaSUcVB^y8gIyh9Yi! zaMiaH^`#@{s8eW%hA4Vsg|~|J7dJ#39;ei!*;2z)>I2e}3MGz)7RCl3w9h~=OFN~d zorneP_kX|HXJ@DjH?4xNflgWzakF4EKcpFY^q}3 zAfy#I87_meU|Cy0aL3;rU9RbMgg+xqs8WZR^8a>3XUIL!8AK5$A>qazde-H2{W?lY zv`B%1y9>cI?i$#9C|O{hArT@~gYZSkS!+_ej*FEp)<|gm}yUm>2*QZk*3Mf7R+A z{WXfLy}KjZuaSGxe3*^E8Bl8aSlX~e6cbUgZK`JdYt5byW`p&I*lh4C23Wyt@G9fkW`oBRAkWMO75DIHo?$xD z6*}+uUzic+>>*@$*gVFek&4*hzJflY5T`G|(SuQd!VsJc{OXlas@eO`ghSsT> z%H@ie43pA{SL|W*aDS!3ew_c^Pd%jcsOds8WK_3?(OyUiU8B;Gvm_KyxTPE$SQiTe%NVx3g%d5R$(9muYp5S!_76=_umC8h?OXmgrZzkgA>J}J+m>ws(p+o*y% zzXBn~98rJgpr^U-_SP))0^^;$A%p@##imb*DEVya4j!>7B2>k)v&YnM=@Y#-xF*4s zB#MHJ6VHc4yETl6B~I)iK{~W1abc-!05nYQc^XWBs8boCou5R7nBBBN$^01~pWN}+ zz0U#>+lWUq%tT;6HSd?LMU!$0v$I$%!HspRq$MV!<-I$$_G1oFD>higUZ7b0-n4#i zT5m@tu$sNXwZ61@xB(6q;2i+^6Hw%51cSL(ol`{2ChVOz0p3qYr+I`SI$nrQ1rdxn zg5I*bgE4SproQ0K5!@eK3JYLQO=6>TusDP!?uht12GJnzqbITqV(V&#LEGAev8%kr zVqju}956I+sbBl)s{M_v+OrAXv{$qxE#^j;d79v-`ECEGaMP8`-m18rN4r>d(LVf8 zwB#v%WG2NcX`)6e`yULKO*BX7XS|}$F!_EPmRJvIA*ricfKW7 z);Ev2)ip48q%n7jns>#PG%s_j>_^rUonTb;Fo2=Te9G@1-_x1VV~{5=VRifBS&VzZ^(k*D)8qG zoCv0apNKdTm(IeUnuWhd@HhJKil#yRygdc~Io$E7@1KQ#NbsitZ~MqN`eK#$n9b4| zrQcD&j*b5o@WB8ViUe`kg5ibS6wv~siE%~_>_c}}E($k}kzrjKx)s90jU)7+9H&LS z`Rt+?8T0R|BQrF-EgIH!6%F}mUB0Z#Gvti;1+7fw(eztR8HXDmHg|8u$mBU&*jtWAAFu%uQ2laWFBgx@dbf4O`VDE-i~? z4r8oMsQT<-j8fLpM)}?0(s_QRzfasl8j&Q2Nxj+G!fhVxTtGa0?P!7ZS{buZ!e?F5 zkwf={?C+WUji!(;Xs6It!;Zyfe(`;mw zHrHCyb`Tu&j z$}z%An#h8$n}lBzP5F~>EOD78;ed^VCG2tlZG3cGoc3tI#deeMTi)r91*7(+ zd9<~4sOa3a2%Xu)wg`&0$h6tFEW3HW{%FGHF~+g+B9Z~homJFbuDbhRB9Z*GQ5Onc zSQ?DIoU_OLyeD&F4xs%FqZ~CH`<7Tt)>B6dxieOj{M5kO*Ho6i&Km3;`H)Wn6Ro8b zA8RDc6bW{(O=ai^(1n{mH1*gn#1w9Nkq<##+=x3ed7P`uDjG&bF)AAK|0l|n86=K| zglJI6MeSw_NWLXk%tR>|nto6r-AhBr0tK2{xL6yUh{f(BkoRYAhPx;hhv^Ps zdIz4_L>X>6#I}zGHhrqxd^5XWEwW=zQ=!tSMMg(AsLW{0%9F|fYTXa5@N z|Nj~j88?l2vj{hXyFhmRwd_^ig^y%q_hKdZIuc%h1bDkx`C96>!U39}#1b@H@l-NW z7?Q{M&KA~fTb0Fnv;xa48MCmC#d;LmQDC!90rU8XGL6Id#pS72;i^9~{*k!@G7f`` zOpK_kSW3;t`h85Y_R9JQZRiZ7#b0jOTyB`Yjf&g0m{sx>Grp0eyDSMdO(D_Cs3YN0 zb9uQVj$d{9HBRrCigHu7Y|bC7cVqN*j5quEoKj zeZ42!=iGF?Ah*d~usu$RO~W_CpBYP(ArPIAxnSGEJ-PP@kwbtGApY;nqK}kA0M`+O z?{-!Q5DQUPjxAK)VjWkHX_lNw>Wyw4OQfQSFD%t&m|ZtE2J3{gcBL>x4wGhTtP^s}vbksH93b7N zEufeIZD|xlT6fHW*vp3)V-O3}8;QuE9yt(O_z(!9Op$QonGR@1E}HebxQgn6>&8k2 zr0d2s6YhZx-0?XzmP9e1{(n%y*(dc~+eTxRT{WEKmG5OG9PISv0zm%;roMpz$RbmxXl9#R1Ta8IZzO>*a**cSeW}9s4 zQEO94QbZ*~2Uz}zW$SzdWPY~J48O>gRy_j`uSqr|8jvfabdeYnB+Iex4l#G(SZi>H z*#5495}HXa%;6FEoQzyb?9Os@`hxoD(P~>~N6)Xw1oXVeOb+gB%^^&_C_;d$;?oI~o;<~WrR)JRno=q4Ut%RX( z_7Sxur@O)k_;W8KkC5zgrRETs}nvY4DIELcXoAu>00*3pj&zgb}X>8 z`Y~lkB}=~DUCz@uMA$p}!;V_akbcq#uluhw;2pi!s#T11{^X`E+67`7@7;38JBdSc zNgOiW#yJj+)KQQ)^lgmI&!iD87g`p<_-Uy`#JuEPRn5XsBtK|mqLn{$Mlv|!RdenC z*&|srQsQpBYCiuK@Nc;rg>Yp|O}w^@#G-C?`7YB!eRWFG( zaIXvQP+?0%{?c7`1W~W5xfbS*Prw9i7YkjmgQU~k6hdqjTL{;AhU)|2`igaZwz~ZT zC~hcClzbrYWN4JeSTgcE8)}H#z7d`i6^jqel>S7e=c{xgG~R?$$yRpLF-Z&B*tXg` zQ%mx2RSM2nI5S)RGnJogSp_oLvoo7!>6o;Orcp3f;R}vskJ!sjj-^xiRVJCi48;xA zub4NkS=xu4;#wR^4jo4v!gkNz$g?n^0Jy7+d~7^Su8Zfa8ti*pq17Be%=cxd;EL;Z z+i>;F{d;dA*O)oYBGSXuaf!%`?fJt3bIfu2?C|a*g?~US-mu1{Cscmhu&u4NFe!&( ziRars;Hew?+)63e8jIIrfo`nFA?u=vSSMe?9sLDO=%BqB=5Evdb9jzg{tewVfOmlG zU`xb(Zs1WfT`cvTWS@H>4py07Y18soM>2uYVfClDqNZGLgQUOqytgF*G#OzFD}hRE}=E&o}+G2KI6N{<4<+P~KR- z?qPl~{Ww`cv1rTA{Sbj6xXbBCM_=1i~fPMV{@hN~C!4S)Ah z2rjh|FEq0nyOtLC^$^sip5_aXb_vz6XiHy#uLPWEAbqQNS}CK5bx%qu433Pye+V+J zGSQZDz)4L=ZSP8yxe|wmRbpbc#3R`f2l^#Gz!#;C4X(r;j1Tq)W=mX=Epez{;!#(E z^(awwY^h3g&X%aomKfoenCeQP15{%6wkq)|toGZnQ?^8nUxMHtRN1`|FW7GLmEMha zNj;l-P~$%&ouc`CYy4Qh5IuuaqtQTEK4alwb;-asLClTB2cbfl1jF*z9TXBN* z^3pBbaR$yFlWk&eJG!?F3Kv3L=05P2@m4HWxE1svBSMg6`M`l9{u|pEP)miI8)_1@t(*cR?}L~GIy%arc@cGpMxMj0|I9zt zTg$wa_XR=}ZrrLwom6-d0-1uzl9ESE(Rg>}fG^pm70xxZhME^BXoAQ^2lw~i=l&M9g%H~*|f+k9o?kU zP1-OxoNJ%}x&L#Z+>Ep@i`UViQgQ9~A(_50v2Cl*oNv+iFtJXH-@eSUAT?alJ5P94 z^R{h2+>$AM86OYw1U&~qkAJMfrGVFlN8*w)58tEDPM6g|hEb&CDb9a}#-jO4MK{!l z{_gEZ^>4WGiCX5n=tM$^Y%IF0&a}U*tSEDDlt+CEU0Rlzx*A#2Xt;oP`<1(?ODV2o zH}&K(^_ZKr*4ol-pL4fVSHAumv)0dBtGP%f;hn2px%t+2kyo%xYPFCEQc|r-M+q^uX%fsR#we6_&CBpI_+?dT1 z>S*uYQ0Vz2680?8!$er8k&*RnWgB3;u*3kfCf3y?>L!vTHIC>8oQh41HNC3vN&X(y z;(Y&&PQp})CVoX>EUeNWCN`Tihp;Ik+&I~WiLL@am8qHt2HVuUXWmpJ8rEW-EmXck zQbtsg-3#7DSZMOnhSBC(J5ttSGbIo0CQjLs;95AxtM{rJLG^yBd$TFG1nB8CwCx4Qr- z$Ni^9m026Zp(+;dwX4yzPN~?Pl;+h;Ut9MbVe1R4y*+13Gp)twnvh=IUr1i|5Ey@ZC+u4>qgQX{g24j#j@2CKmb z*D{jH^qAC}sKl4`eWcGyrPoMW6Akb=XI0pYsl+#?^q4ryXlldBaAh?EX=F0W=7*}m zx(+1qJShB3Y=oqo*3r?kpKg~AU$F9Mk^fV>M65V2nar~Q%OHo=AAJ(lV9xH7>eaqEB)#M8> z(|@?}6U-6O9&Xa5NZD1e)Jh)RO5yXiQdq9@nB28(tP~=g6F88GE8LJ!hMZ+~^asnK zKkEEPTl2y?NbSdCI&yfIY=@kU%wc29vb2*m_>VV@0wHnc~<>$Zw05p zy2i0km|<9Mfal5 z8P9td8k+JM#|nM(-$aX1MO!{A^5r@c){0w6^N67=uJ3M6%Qo2oqUcDI#6?|0 z|A?)O>3Ho13l+p`H}RLTT}zYM;KVP|72;z!eTx{T*Ydcz89f<{fustZCNj8VoH8^TGQA#xh&P7dBslXV$ix zenwlKf)Q<9qAic{7w-Irte@rvzDp-bH-QR=rgp7233N{2WU#0DNU2Evnx_ICZMpLR zJfbZNUf!;k--{;(d8I+l*30(`US6-4FJ)d{VUUe_`9#6XtMzhj=H(27d_^x4nU~Y; z~ys_~TZJDCihr8F8WnZ7K*L%CyQ?jphLtYzk zI!rD<47Xu_XUI2XBEl4DcMrNX=kDRX*)k@>jm5*ra%9F zihlp$vF#Kly(hZxqZXU(VSZ#nIm{le$<3!-pHM=N&f?u`OA^;;5s%X+og5| z8;PWx#de4tV8oc|`3Pp9Wuq;TwU=$!6FgeO)?>q2!(QV@reR-g5j5;$0ylocP6HPW zyPTqV4U2d38}<$KDIIM?Q?_C6^3FBP`{^GV5Edu#+cwkMwn=Tf0cmR2Nfwi}`#D3* zViu^Kx*Q+8eTX)awkl~M%gK#~Hq;-qQS`8%7s_1NzjM*)Vl69ZetdU-zi?LyGd_33 zll9Fz8W~{H{QNz26rp#ucLuS0OI!`;*h+M?2t3i1gw^9*!fMxCcrRRY~t?ph2PJm&B!?7t6MiyPwnXZhc@5g?;%c zZFYsntFZDv+6UVRw0ZB5A|PXgj&Sg&3jS6b1NotRdJPk_9KLn`RU~SE!5XZdbmUma zkdo$Wjod$gq3xunkW#+&%~Dj-oUrdx_5Dyn=6JDln2hGe5))?2p43HgF7!*fKv(?i za@#iRD;|%2HATc|=(eYtkE=zrZ8@IG^6c>|whlC3Q8?bu+4w=DuzXyHmJMZbGVqNVlm?^=|=Rm{q_LhhA zTl?5l(QKQdbQN_Qej^qEVe{Hkz}xvn-x8KAj4|egBgq705;=B2wFZ5yWeAkLr{>?` zQW0h>(UM@h^+R_)N4M(ud8HgA(1T+H%A&_dPl)O?6#Bd0%AZ)0Bmv`c9GDH9qkc*(y*f5Cy@l;Jy6vw9nK>h4xPUFdRljZO->Q_2&(}Z14;JBm zWrh}7kd+6^?Z<#XVcatB$!Vr~x<1`%gGbBkF*EzxE~uuu`m<1hS`mJq7#j2H7-|CN zgTe_ytq8xNFUe3p{ZSnRVPveA!D5EtA+-4EFTl+z?+RNEENP^0biwruN$=bxTIFr) zE+*ATS7A1;^!75s$7|L7g0I~SmqsI zdMdQ}Z0N9MUIklWI~{s)Yc%mb{kfK0j@tNnYpN1oa|p!pDs2g~B%9-Vmx&!DqoEJ= zALnpf>96sV->+T+kVsssW|$ob5-M-(Ieh&NPwzMYy)|%K^>m;lI~G@x7yqbk+8`7q z;!qEjyo)F^oqxl3QY_ptvN9bxj`~oH2D6J`E*DI@WJdY@KT>qkCR&_e>q|SW+|eo| zZndzX`*W;)bx^Ing|VO2y24xVjz3jrzxUPm68qkX$-1v5>sY*#&NmEVC9y>4uN$dU zA-swtzu3zaC(ZUdn}4%#ZvOq{+icUOY|1w6AXRj?!f6Ff)3(6Rvb^g4+-*MTLsjA; z3&52ewUy>jv+&MiI<>P9{;Ql8Ke))Q>^2@#?h40}{&Y!driMmh=wAHJ1O~f65rUm2 z=&SV`VT^}%)@&cI_y-82@p3k1f3~?(hla^8psyduf ze4=Y04dXP)f~%A_Yo~-)9EV;EsNS@VnI)T?ZoHuHMH;?{gC5Xo@&M z%f7ZbP$zr^oifehHVC7gdm0+Rja)Tcw5wN$I?+r z!`=B{N&MX-j#FmURAO*uL70Lo%<`Se5upq1cLAw%19eaO=gw`n{z(vDm96 zAenuITf5yk$|f2ReMU-BMkZm>TjGBnwUXurkqT+ua!@a%LW zi`N2b37xcTzcS9F1T%=kp7X7GOKUc$ zu3-F6RDWIsP^N9%@eqUK($$V#Z@?sD8rfMKZJ~TyjsY6^LK*Q|@ADjnWsqJhq`g2| zr1$f)icPUqhJN9?xB9bS))mlLKVBIj%a+N6<~(Pk+BEzwnF_9?0%S;3mZ$!0JSWzg znAb|*Gf*4)W+1Q1g)|318@s;4vC)ZN1tHkl(>|7CZW7fs`ZTOT!68o4#vhBBW2 z+S^@jPGA<={Ef7HyD4behCoKcjUO8oN0r8g994Ez#Ac6CXxpC4W63B}%&1Zw-a_gL zrcoJ;l#D!}B9>~bRyOSnle5!{9p9P?@s5e6Fa=y9G8hfqo@R@tm`@cs<}0NJa=K}& zTP2P+Q=eq=(VU*JX`U&68!`ukb)42y!cG4%wP@QQQvcw$irq)Cw&D79kA4kKM=sFa zfU*w98|jfpsYr|K9J@aLPPI|TuJ6msl+LM9$=fJNZFiAYV}cQgjx~tZgc~mvDx=|i zL+WVI#@)i1lu4$q97v_Z_*20~=1mKSoW%zze1CJ^2|U{7yvPsC=WNa!x(z=vy8C_W zN9M=S8@OJ++Wv>;;CRKZhAF!_PvgQyc-W@u)!v8oYBa-wMT4J>ZJ`Uk<`o(=iqnqf z)SH(3oQlqQZWO+24DDr1_}gZi7F ztp}aQW(iU*&YF+Tqn-u+PV0uwkocRstZfqOo}u7%Q7|3~ih5SauNf`Lqfv>+f2mez zT%r<#7QCbKJ^k{w_kc1+t@a)$5Npir+?#oCG0KoN!T6-bW#0Q4mgFG&M93_Qra;%o zkSj3K3cY&V^M}5W;#r9@81gv>6n~L~UWnxgj6Q2f(0T4|pX=XI4N{Hunv!E~xh5$NQm|MWdS;}xGP69D^Z9MBf2FFhXA920VpF+lN8&wd-{9At zIra)G>MW0{iTf*=XZ6NK%=kr5z6yrjMZR|16VlrLkUW}`h#NoG6mOH|R-(FGpN>}C zfDp_$=C=1`25OyEYa?Wu;akVgT-t->*6Mi8(lQfl9r8D6X}K4k60jiLq+33Oa1aQe z(+Sl`)6pbXWi)B=+@*SK%wlVu#Ybk*@Q5faW^)y*khO4{U^x^e7cxs|T8goJGLmk_ z*c#^5JfW9o_8wL|6r+tD%D}HlJlxxk{$U%3oNn#7a94WW(R&Qf`7syr2jpW0!4X{L zm0qWp;oXcSa-eaq$4^+?ZZ7?QjD4w<+QhG^ada}g{)prnxP10!s5G{KHjmXzGtskWhGoJDXfqMcZ(4&TE?a6kq_GaEW$>Bv{M7bn=z z(dwSsZ|JBCHgtUTk+g~*)wz}BWp!>$TBOmGpKa)P<+B{1dLL+v0l6_734f9UajXw9 z&LBRrPLG`RX%55yAEM45f9`6|L}dQQIY3+cKrlvzcGy{a+R%a8xIV6#FxhY8wUn6o zbH`~zSPOaPuk~zQ=w;Cel%v~Wseg$OyrjP6VB5peecAi{{F}dfnPEuUx%)GrH*BHTG zu=itttLH_uDpU?v-zOti{Hj_ZYF}!2x>@b?_kL{Qz;AQl_o{P}k(vPfXHN8g`bmNN zdp}-9+Gxdj4*Zu74ZK$XzEa@-68Qbnq<=12N!h3_rl)83E0UGaq!hY{bnmR%I|&K`nY0W9C1 z*h+Mjv;Y}ha6jYCJ8r()`*B_G>1qfX>a^ve>5kqCu%M}C^QT?-cBS-1{{D}Ld(YR| zUo*ZKW5YP~;jvUDz0njiv1pplAKQE}ome58KeRUrHNuovZqEzt`D3+qinfWURJ>}k zQhzwcJ6=10fAjgbfPc71wZr%qJ`(Y3#PxBIGt=;z;aR89 zWIVE+5%?;}8u%guda^|^n8GjVVJ~HlALIwtY$eZ^T|di_^ceGo zrM1V|ws+x3tng!O2g03((Xsd~v(zie&M)%^jjFUqHpwJ!nXcFIXYJ2^YY2sSqbG@T zYau?|bRS=%Em6@sQ-GDBDEPunZ}L!!1znYYz+$-RSwY2bnX5m3WmGc9-aa8EX2;w< zs~5_OuSp)$F?-k|AskC^%s*_=cK~}vTYd)}He8IEFm@6tU#TDV0c$aHlMb|`K{_$_ zs-jFlqoJ$MI-QeN-+P>!L@XzA9gAoF(uX>*Gxg+l;BjKeRKH%%{hI8bIa_C)0J<|4 zTe2ibiO4PKksPr_>n$)jbf{733gX*kl08Fe@eY85U`ga#QdQzmDC ziv@uzDJmBtlZLa-aU$Ggo*|lf_!(9jpm5{9ki@ygnwVC3KPhmdxxx3-cBWk++SS|) zl-PE=+H>~ane&$Bug{2zVBcn`ulZ>o_V0o{6j*oQWdn^j-0BnoKP=#9eBj3gTq58E z6QTlUk%!kS0dEk+SR7M3`TLsql6+g#|-l~NP%qAjlzO7OnvZbnWOFgSn_fv`j z<*q2R)NF4K$68rrm3qcZ9Ya;a3} zQA!kvc^B@{DvUdmG%=U-fqAK!kOb3iZ3al{m&tU|lE{ zzGZRY-U%H4?HN65MXZ)JBdhq;##Z*wovO!P-E1}bQ>d!@Z<^^UJH%aeJE*!pQe8|} zFpnLek+j^*Ht)!11&{RZPT^-M+`J45eVeC@awv+_Koxa2N29=&%P%|Bj%*HX4M{@= z`$2I|Gggsr}&S#IRJW^F+N(WW$PnBGwlv=o#&z#iSqRgQQGCP~rHS|YY zy}l02a%awfA8rN`PVj%e85_RkARp@=z?zO+Z%mV+L-&h_7XWI0DNDrRK6s^wpdxKl zb8U-{Ewy@SmfM6S5qbiC$5@V=%s!YpRc_mqU-F)vno)gf=6k>T zWcb~CjF07b!-7#<7-YfO1Z9oF6l3d@V-0GX#k9}Hrm<@7I#Yd$v0~QX25^?G_xG!$ zsltt;!s>$`ZM*WK?)puNwHrbUWD&5BkL4_8`BCmb>Ds}T)Pz$pxcwRlO!|@-u0MO) zD*Gp2Ff*OUfH?ST7{JWrwqy0_!(-}U88eBJYFni4waZ%?yhNUh8ikW=A5p91;X=yv zk)S3cqj2DZ{lgvKV(g7&j(g=zL*#BP7_ZJwl#CT!tRlOW`lF$W4a0L;$Wfq+Ij(bW zU8nG)u*zt=dpl9K!aHTW>z+i(4j=$F+<1+Bvc~n$w5!H_trqx=V-2L0$CT_oDxM_g zEzzq){r{VdyWtHHX*%~Z%EUx-GIFk$ZCoFkul-5AmLSua349t&R=Gr|0aE-h^wsj% z;zLh1n$ikGcU2gA*Pv|=m%6rHeX?IE*EZb7yX^L&x_66?o7C$RK$Pm-ydG|>HB6zm zMLoCbX-Ou=ri~s7h#tW?Z>36CRM>j6+$lK${*sKHEUh&LZz@KFTdLd8P;km5X9%+X zewK*TDU)u?FVRlfYl@UBSxY``9dgPZO$oB?a?R$t!tgSmbFbX3>Z-i;^nkccrZ4idS>A6$_j5eVF8lSwof|pC`8&gx^5dM zYdfB3;|N_;oA};_(M5d8O59h)r=v?>wcZ!1#yt&HXc8QW4H?m`ff(D#)}5nk3H`al zUdjJ3=4TCh*O}_1?N6hiEeikd&TLbs`<*Fw0EE%RW_5jDht_XhtV3~bht(!Njm0Mn zYp)*DktapGq@>2Ik8tA-VDS?K*72==0`B2SG`jxy*s`U>#nZCnq_ESG?_P1LNWA!L zOBEYNr%!K{n$e*lD8_@CLGB>V){F$9?JOwrA~OhKs#JGfpu@H)4x$FSCh<{q!on;l zdo15-rVu)|7Ob!EXIyP!Gs~1c!n>;*8;)im9R_)BAoZ@UY)DZZ`=x-U^PhYy99euwJG7$Vhi3?Diu|b+mJT zLuj5*H3*4m?Mr#Zv_izR+R8cSK%J;bLib*4k{EJ=VbHW!2Vl5yAs;x5Pb%d6^JKiK z&(Vw|fNW9~RDXxVs%|>__Ba_2B6R%vrXY{1Y9&TDFNlAn{Q7_+?tLP#E3-k3l zxWD1qd3uUJp_kr_V1l5nkMN=y3B*3y?qE#S?rKD3=o0D-H!b6%az_g8iU>FTQ`j6q z$BLjeJhl_=9*wDjJ*8oRXB*u;lH|_b0)XQj|R@3_2Z>g?)s!e>=wqH8(vBZVJ zM8hKG>MWOr^2X)Pe*A_C(~-N?wst#I&C*00{zkTX!veG12!(66;-5i53ub)^!eCYl zGDoWun^PxumW5tzTMf1s^0VMBR9brv|XN#s7;g{XTGsb-)p|$ zb39b-qsdI)Yv^1}-y0;f5~o|$8EClQA0x_JEli*@io%W4>`Ul9xKKsjP2#;8?Y#cB zCh=-)$nb6r2gMSXGdZX0_o+#o&fLs4o9|_0=NVcSX{}8x8L6vlUN`@(GPH!c8?LZ{ zg>vd(YbQWC~I$4eD&c zJl>=w@T%l7K6OMNng%=S=HRgMG)zzNXUq5lO)8Y7wVJb;Mp8o!o2sK5T?%B3iEt4Q z9qYRhQ;ViwYwN^+xlL%ikV#YQC2**1FS)~5vpM7CI;f2%tI=l1zNpS~Yqj_L<+NRe zDC%a8TtJPnzP*+w^7m+$_-p#>-LkAMdsn*bMG!e%_8h;^W$zB~UJjTmlSzYMUutNl zfzTyRJwT~Ktt*|vS&MQoC4sCmP(Z+WFD4?u`4M@%gwOz0j3I<%G4>B#!!YRTeRMG% z5yw0$Dv-yU>*-SBL1>qSj4-EN1_31Pa-4nB>4CWxKjhK!z>k)X>`wlwqf%yWRxvTz zR7aT&M{nWn$*RJQO_LH1KRV*H{M;WXn-(~a=Pg$jtJLSx0(Un=zRHPR=q zdW_bvC)N-&vC3kp!_6VDcoC>vlWv)B(jCEPe@@;-bMjSmx#96=82{TLd~2KNKOCfo zlkGu~*gf=E(~JoO9Ub&=m@8c8Ko&+@Hd0&L?tby_^{}-O6K(mJ2Oruuacn)bVrS@u z^NfGe4jbey!|ZU=dCqZG93gcozXvXKrRpfv%q#;1$3a2r5QD3D?F(A%UO(kG_$c?~ zDScroa=eVTJmi1w?>^sF@c9n^bE*4$MZxFW{LkN%T9=I1XIy1Ec2kq+X~psa7~&-D@Xai3@F^E%_~pZzaeyDyjM3sHuE+Il{#!D^~!A)$)n z1VVg)Zkgy8Ugf?F(HB%?Q1}L)gO9q;yA*uB&i_2yeg66L{L)wYpD*My_bCZ4RIs+f z`_z7Vna+KEo?h?3Ydq)N_vh;UFSx|U3dAx|aU(Su{}@#+I43ha+Hw-0Hp)`(%7xCv zL=Rk4bf*7yah`%=YC1QIZy4vh7QytZF#TAf)Btd2>(GD}X)SI3#Bl5*95KV8r1tr(XfCbl_x8W_HpDpBnD=_kVyVgG)-kv_nOQeH}_l#8JsXs%tYHP6Uw=tH?L$`x(Z6JCdxu- zKf5AwF^^8#o}rZ(VkgvB6huf?gm_^x?* z8Q#2B-*o0gA~LQ;->&w*%`#6vvKI|w=Zq!ZpW}Zz(u$eUqH^|6`;O*I5Zw#BMzd=&=ZxfS z`LRXjLSHO#v}~A5;99KmrEueO>ekAV_vmiK&H9)<+g!Jv2E3*PxB4-PZP8a&4iF3-@h+D$JahSMujP-Jbg3J{lFx<{~t=&+a z_<>Lmk&^ZfQSBHdYjW~`b>f$z-#00m8lOOCwJ&U^0A6#7R3mBkXX5(ZbbPjFJBspx zlLPS)*>S$|Z;lhs(E~)8t%o9qFjJU<+sxXW_@sScwl+V*076%_fIE2#U9H8oZUP_D z38VFZbDh!JMIG!*6~fLmWozfly=TX|o*x!CijA_^#V5{H34C=M?VzrSkA+{~nk`FY zy%Uy|H7z@(EnQr6O4}W>gX&*^^jK1N(u7JyH9>qLz%GbiZGGzp@!0_cCD|apjCLYi zx;sP@NuVV}XyCXTq1B0Z6e(ZrJ$968U2D3;nnzrm8;e}?kQY`E+<{36NF>({gE%hFsLww7930kgSC{v zsi9de zgjpTinLHU%zrl7E6MLBW8TW@CNm=85t7s1xPoP~nT#>KPvSR&?HL96NMQhc-SDl9; zs+;7Q`hzgwexXsIF~tPTge!Gea=CxP(?8_R>I|P`$zvy~lCkr=VJ=Kydc`i1&5WqP zdErs4?e|)4h#x6$@JlrYd&jo0U)9>HsR71E;IF2X)7@Pt4 zmjl?X0N{`ez)cR|*Z1 zC=PP1K-M~tQ;LJk5QvVU0gLj90&;U`nIe#z97vDiAQuSa0tfQLdKjbPK4Z@3TV}kS z4U9iV>r`epo-=wYQSlUI0}67~zzG7~8qjp4|I>64COCmwf%-oUJMqqfN_Rb;LhUCUUl@qNGddq1BC zbMNgsb?VfqQ>UsUMG@bF|Kdx_74v?^eqWKY91; zRAG$Q?V}2uB~fIb1qZh+;xvXtt z+v@#w3s1QIIqmuOH)IvO;El1ebkKXQtUr$0al$?4X2Gp{-h-n@7F1UVKqu^Ugbeb? zO0fEb5n?hY?A-qV8iTeLy2JaLX6Q7x+F})3IsTV zzD)i*3IwqXzoV+wtE03tp3>;nVXk@NfbrJUz|>@86kw@(wmJagWd8iG;%m z{KGz5%;g(}W@6nRH-yaxNB>cMDbIU~1v*x^iDIv?Ec6TQ8)kh;U@kbTFXN%#Gdx^a zv2?MYAR?bHN?yX#6r&YoUeLhqDZGKyoyL9WhseBg3DO0MU|8bF^mSqv8y$x+fDQKS zX4rv(Ej8Gml0?WzllsL53-@A(Gg19-SpGy6b-p?em6WPEO2LAvlJiLt*-J~XC4pZd zxhBl#ZpS*iu2UXLYO#@>+-tCN`oB~~<_qZ|t8|Ad8jHdFnyul=uL(xfK;7T)s7Nmf zJO)xy*R0!d^4@$(Y(q;?YKFy2@|-*`&|Berpga@rB#jjPg$qsE355<+Ar7*z0|RuL zg|rwK1ACwKVVOSEug0KuNB7qN4Nd=om&*N)lJk`g3CW}>lN1*w>5F5SUpKa+cL_06 z#xEl{vQTMolM0g^tDM6~_~1O4!?ayWX=u3=L#nvm!(S#Vj1tL0scjdv6@HR32Y5-D zY#-KT+d9ysHEkRiVO}6I*e}?VxSt)5Un%1Ru~t4NDT}4NCZ0A{2Itu7aq<3-Nv`qy zTFuA&$6v*5<52xHuiQ=QpLqDW`Es^jHC;3INvvW{3NQX(mJO1X=BvM3$x#QX@Ivb_ zv~A#J`)q^c`qwo`N}nWiNDG|l?8P(aYh!+q*BkEQL;U*5UfkZk1&*UKc1lBuz7Y9G$4D0N?k~uAc&1zIx z8Nap2*y-<5_Rci-D<)cL=SOfqU}fx~qUlt{`f-83kA7&k4X?E0RCCTY&pFuK8%Hse zwX&Fy#@zF1keuXswqs|%C)5mY06hco0{0JxKz~Ao5Yv2mG>oDxHX2qvB4oh@go(iEjfUrq`P6+g4Xe!srT@-FifO7PEWPdq$mf#&gym1oxKIkmro(KJ-%3%IY0}$5oGaZmhfxD^#*X*gYj@>B0<_9~ z$%Nk}c#VRt>D=g1@RKO05C!>y@1rplzRYy{%|J!wjRiZ+R&}y7DxK0ltN<2aJ=H|-#O9!65+mg{ zhJYluu9GFVhTpNy17TP9kHq5{g4?9R!}yp;un9Xd?`%WAnHtjQwUVp-hh;6Nx>ogD z>uEBmHhcp#AshSB^LDZ;)SnJ|-(ot7x^*9GJoq$H^f6HjrK@ znq_|A!8R*&r|s`MbyxId$VNm*h7E~J>@`><^zp!xFY!m79b-zK-EDfOskn-P<779* z!#DdN+lSJ^vucE)lXjJ!F6K zkZqqv2E9V|%ZtsFy{vhO^EC8H$GBuDJ5R{Y2U&6m2gG)$z5vxHpR-AjPOulKY1l*+ zr;+kGU(he{z{6?mX`fRlQ{f$jZ#ww!IUipp$lzcKM`rhgUv8Aysn3GM0zhXpOC(}z zlImmxIne6?P0qm{lD?Al)w^&QQ9(t?Yt>zK^H`x4_MxgPh?D)IC2Ojgh>qd+h1Em( zokQ}R;8!Xc55LSDX+3Zl2=R7_7?i1KN{W>8Z#}4IfyzBRWT*$u=wM(~lHtMMsH_YK zEp+#QerdW_;9-MB2ePv?F4`1^`mGe!d^K-eA#M*Lx*=CuOjBN9I&9)U< zaeEYYmphoequE?m|K^okXIuucSGqHL3OUg>45rBZe+c53 ze4|RH1G9Jb!X!uzLk(6cM}c$Geo2K-_No~anZFJs)=1cX(-O_!Eq3O%9{I$LdK>x^ zmXMHdo>XDGBZ%YOraxMHtpCB@aEP(m znRn7AR~1Y1@n9Ik&<;C)&+U34WB1GC&Q_cS>-1`SvZJLeaQqY2a-nX<=po~|w~Xge zn!->EjJ@3Rwwmu`Tf%7V8#yC;zHa?|s;jp3r|r6;X)p*|WW=A-=TlvKA70S^!}FfrmbfZq0jh9T{tx@@eXe#rZ8oKN-SJ;d_Pm#{Gp&4lkc=TqG%8sgy*7M5m$ ze-G%a^Qkrh&n$D7sUka{Y6y_IQ_L5Bk^h_Xsb+Zfbip)%$_MU*ck%GrG*N$|hPh+Z zPXBzWvpn#RA2#sz>KyhDX_-KK@gOoEn9^!#N?}4B0VV|4^KTzPK1pbHz-rfVR z^T1bl*wt>EfH&U_`00S>oliAfriBxH^(c z2IjwWKGlNFBu-rOMHy%@_xl&XV43^%y=_$0qZs`?XN-YwIe`lA1trH-AH(@WvifcK zS8d`$IX!p4bPf;D5mpBAFFq{b@Sw_A)hv#bTITJek4>It288}MUjM_`zgpJ4&Xt;c zC;wLSZyo>E@b4M^&E%iUzx4u~$iqhd&DKj(viFj8fkENuRM|)Q|opiu(MU11ARAFrRv}ml8V&%*s+J|5(r8EiOJvX413a@72 zI78JyHSkm6{whkpaJV3DSt@*JHq0QwtQXAdz(D7RSR?3H!H$=M+DbCfX?J*)c#)4# zLsU363CFdD!z>|CJprF&^0C;`;+*B3d>qEUN+BpX0t5p@D5hj_3L?2Psn2UXw+Gg? zCG$Mro)wf^u8c>_xOyPDm}Tvip$5a#Nq9C7!oteqjuticRJNVxc0=It^hqnUO}agc ziB+O)XW@JdoJQL@S+t!GY?`*cTF{obGeeu<*+qEH+5&BxBzPIxUb?MS+CI81pSC@O zGbo&tg(I}96VqQS?Rt>1S@Lfb?WNMI2DapuiDI9%%6cvdUrIat-U!!##cy%=U~7G* zH(n>-4IcQtVfgnE{&C>fPuE31^#Wh;H8J#w^71-pi$qL4ZVYf zil5>&c>o$Qz@8Sj?=E;qI5EK=XVBz$V1|I>;VUWZR`xJfDNQ@nV8k3GVm=;VRsES} z=tz8$yot>1U&Z!Ut^4ocZ+&GYU*iZpkd=36+s6DoueZYzrGK-fG(Nl#^@VA+)LB#> zKgLdVCauyU^=zcnV47U$K3SN>{c#>aM~k52L{LfKVIjO!)n{+}syWlIqAyjHkPwuqzFW zH7pOVh7p>aImT$U2VCwJYcFYyn{zjlJIO2W2>#o>M%rpNj<7pEm6sc#ugRQeBIO%v6^0r#mLeTk^y z4T)$Ha6EjSB;pn3d`M*wdh#%WK9oHCLj)fm(ZEoGeRHBad-6+2D@vhrLv;wZ9R*eT zApSdFI9v8EJ=Kxl0FCA>!nk@#V#|s4sT(tFGFeR5{iW)Dw@erU&k;B98+%1s?T(cT zm1%6xGkLYfZXl-UE)4sPbroTZ2OfNYV#uh zC=e~Rhu=5id?U(WzY$qS1DMYe)K824()9EtM!}mmWu~X%cW=mOisG9=@2%jajfD|F z`qPtD_r0oHeRRv|4|+8(b;lZnK{wHhK7+P;*4GcE#D}sNbP%t`Akz;scgWQbodp~Z zzsBOG`+`}H#-NbLpkGAAu~0!(TS0S0e7Lt>#AT=5w4f2;zSGVcAIgXLI(=*mYx(Vz zc<+VoEGc`|uIL_1%Fa8~hJ19&yVGsZtoP)V=bkR+O{ZI$zH)*5(f#1tdgR zbt-&Da~~pLsfJU0;oe1vYd}1Q4-Dx6agz&JhFl1!sXGvqNDKo=XY6Id8sjytrHdGl zYHVy`p{ERcBt8KaF17hfrbBuXkTQk6DQ9>Vf0-Vh)sooI_I`()=Sl1;Z+Nap@w|TPE^0QTBX~Ac#Lv z_Ppi#9P#JckW+y4#otg@3H9HOY^C$*+X?uU&3zVXI8DTyq7wI0g3SPZP}QE&J`P(f z6&?(CWk1UEi`-xAVtaH@e;ztx$sz5EB6-`QH|`SqIqY8{5SNf68=c@nU<<*gd#Df1-o^ z?lj!j3wJxio$DBS+N_RXrP{qn+S;4j3K&Pm;uP*i7K_*OYAl|AEo^)<Y z0*;55VltG49irlDRGQ!Mm8>0RCTfGYOAx050WnX3vSBJ3LQbdL?!di# zsfe+c%Y32m5~tO9?cM3Vl_iA|YB0QivGyC@D0yqa*Wnm_qXS8ankJ88mV6pwv`LJu zVarlCPp95w5uc}dpZQo*;C~MC`8f1G`~0l|>&PrlSM;DNx(knY3tmk%cV(fK3ul$p z?77fwSG%qwONlid8&ayTGf7zusZ{4Sb5gvA%HOX7l%p7ySH;dRtf*a32@eVxT61A0 zN@e#` z**xB)r-0S)!`B%--==ta3Yej0SPqj}KuiHA0qN@uL;a0VuOyMbMb|I|)HKHG!EMuSlqWKD3oSrLjx!PiVU)07>(u+Bw}Xct?7!{R#)Mc_JwOh*#tC z266edt$i-L9+wviI37M#bL|Ici_BDaj=0=QWLyRr)Y=Q8(=0wV&0@^j-^b#=F~_G_ zoO4#AO|vWAXX%0rcdhPH)%_#KEwte7Yi#o6w22Mm4W+_8AS*M}&K1#vRj`SIeo|%= z5O%mgX)O-}m4fIUQ;-U;Wl1ulgskv!DtwI<))9HntV4sd-=k*d2K!mIPU39+oa)$T ztHbQwiZjjZB>6q;$bg4zCeR&|o1!{WfZ%LjO_r%e$^8tV zRuwrNI7F)Xmk>JDJ5r#pI`ncvHAKP(%vKsuSM!dyRfer?yHP18+`o?Qbe6fVbcEf8 ziE@W?f&x|^=SW=ql^0H_mwE7r&{JM*+f?RORA>KV{EM$yY(S--&mfaPHAV> z$LuF-bc?(v*#mtOA06Dv2+`1}{iSW_25#yCQ{eVn#S^nf@4464M1T5o_893oiB}sV z6X2iw@K*j98O{t}^!6}~DD_0omKzZ)U3M3sPjJ*z`qWX#j1#*RtdJ9BIEXUKy6Ysuyq1k;DOEZ zzy?eb*ti_9guw3dz@~d(Pt^)6ngjN&z$O@&g#lIT*sBFsm;?8V;EwgsE%4C2e3ig{ zqDPvE>wpiO*b6WY@%2s6W%Rc+mEUE?i=etu3v>~n`CLIa-N;NYRqScP_i+GCJ>7YCvw8w5#;XO%r%65C)7IC76Fl{Fk$~gj zdnxQby`9g&ijpOawFx3MqWX`ae&e9+)(`wRiM8vs3g7mv(D8m;S$uXkd(}oyt}O1~ z**nt1XPC)C_R_1Z*?4Z67Een8AJAs(TGZ2R(==sTDdpUWrobBY16{=dpz;vi zZ_%?pSFi9$Jzk{VsY_r=0$&K>)N~cOt2a_n{tYVG^*pS+TC2b=Q=y)js^{)NrXHUq zr>dUb)U$q*hz&^fG<$cG&SUO7O*YEF@-?lO~ie;QnjeVFP(q8P@c*pJ? zCcst^t6oxQa_5f60?5dbVY*0|9syGeKcS_hD!H%4;xuE)Z0>1)fNTANyW!TG2tABr zi^BDHxdm?L)kJ9T8pLEos;#%aw-ay7a1#X_5C0Rt!o3)UYJ;$Xb(T=WWfGxUQP~D6 z5ypRLHuU7Rf?`(LFrt6y%E)w&@M_cP^l2bW{_0nD6>n6wmw@BpZ7J-gY~u1GNmf<8 zs=94IUs`omRNz?gKO?F~++*60t_e`)vzps-dXKI9oW?*KJ5Bh`$Y z$ytX%#cx|Cm>dybU>F!fjrtA3R`bVwxm}vDP`&QhY`Q-~Tm{6L81Hh0U^aTQu<`m4 z@p?a>_$`R>dt9u!v=H+RabC(ijDmF^%VL8kAkPZZNBc^QbC+CNN-+E#_s zj+fC(Y&cRNaV7DC@clAx=FpQnpOBnCK&_f;znX=rCbf?ZfVDBiI979Kv);aoDappc zOq{^C>z**aX0YWcWAhb6xwA<6S_{#y zN#dkNZ5bS8P*dOzWYX~%6RN+KuJh>o(5LUSy-k$+sWWY0wXU`=^sBpV9T-S&a{1#` zs@ka3YHVC%zrH9S_d_(5-yuFvKKJXqlsdP#{_ZL6{i;Q@uegn&U#K4s_e*Bh-&0$m zvn8om*zcgbQP^x?)%CJz#r<-o`KUz0^rJ9+S@gRUH&)9@kdl#mFW2FfP@Rs!MFl)t z1K;X?p}kmX?B~8LGf@3D@5J(qn5%Jze8Yn_#l-BwwmFXZl`dCR<># zuBY(#Qz0Z3*s57(Z9q0H2jcd>G$Y1c8_*qXnhrC0*pRqnPt!;h^=J}rNF17vjiLux23Rqu_(`dr!)j}QoC9&Z{Vnm z)z7r=I6FMg;u)pUf%!45F&>`5H)h0V_~YKYsjX+fpol~D_c0tio>lm*=(mTBxj6NP z>L0K%Hz;T74b@-ISD&HC7j*zp4KW=xletIaP)~)-F z^GSKC@VD#+Ga2mGnfPE%eLj60qKsZItF&F~X4VTTDlMCHh1=Di8=$2(iYSL1vy~N^-oaR|*RrOoXhEVM zJHuEPq_xKG`2v=aLVSp5oc5a1yUJt{NG;ZkzA@arLxDay-yi!13@Y z6n1y;rVx*&D;UMn1Z7Rvil&Em%Oo$=T#^~=J2ZG;B7M5RrT}K^+FBDQT#^bO?hA!E z>e=vd!4EO`@PrGbR@lD}pHksXV@=^_1K%j%Jpi^nvX(`%(p~(sW?nNFJy;XIrWu0$ zp}TmPI}b4dwP34NsktayQlifAJ8c!8jZo%vr@~`$X%b&{cU9Hc%@{UiA_d zCeld|-}IPBX$L80)qr%)#l8W?ss@M7u%g4NMt@GlZ@*;&%vfO?U*2+0fwi7!Z_M9* zOcyC*;c&(u%%^r`H-#ERO4G}t(N^-)FUo81;k?VZGg`Pt6 zgH!}x+BB_F>60n#hxGOZCSw5_{`Un@Z20j)Dq=d^grZH;=Yk6Yr^p^e z6kn)j+X$KqxS31_=nC*tyl=S~0A5Uh(+9jM2k;vKHh6&30eov*25?Lc;LifQ*#Mbi zfV^o;2J)yJ$o5AAImSb|0Khdw>ioLHIe^;=@Mr)5I)_D*W_9o-9BOV%Sa3V}Rb%%k zpUj=RA!CDw8jOj%32gn&t%^$PN+4GQaQr^;UW*B0PB|;FzPZCF6<#+czq|HPP1jmY zx$35ZeP7u&uhvrDLk2^2-U>tI2U^F`_5uvitN&?BEejd9zDn~Oa=6g%Yv@~?>q}ot zb#eYPRKd54q%$;WtZ$V_W*vgZ5OEabIm8Yt|qb%RaFvZhxj z{3>G9iY%XbevSlM>8MIOD&4A2?F0@HU7~^Ity4@59fN24JJb*}tosfoV0wDxnC#5- zTHvnTXx+`I_fidvn3F}!uRFD-d+0x3jh}_gWsM^%c&Z96psxhM#GZz1U zy+{G@jj-E<-XJd%+K<=j$5*XX_+zNBbEv_6c@FOBf|?0bD}!fnXPZE+K2&C#rke$Pnbp@hyFUBz z7X5gVSKsTXjdXom<8_?%#(*W-Q#A>@YZURf^L6Oo9@Z2U_7HwYh&pun`_6*x-$$k<@r# zDv=c5Q4LyjjF?;a1Y+YEXK@OEp3XZ|#BAEZROsrnrDs>Uop-X!hMs!13^t6n0m8 zn%Enc*Q?4Us`5OeDzGQCs^f?Q{I~XA`~ey94oVt^FSb!mP^`X<=ig)phP?d|jq44d zQE=|QU#I&W24C4=q`fQBmTwQ1lECglJ*mYm3{DLwXZ*)+>uesA9fFw-2(8Sxca0V% zi8TtyUGZgBO(CzQ4^`7y)btRPgQbXzhrYfNHKiPqr?1o(ACZHAhezP zSaxfD8om~$54yG@dMy>7%`99*m=y#-NnLgp!e~mWEh$9q3xsqt%Cu|44eIU9RDvWY zYN*Fs4#gMbs$4Bw^>)84x8R5=HrAEeG;Li5O%=d~>cCBj!0tqOd}(|E6>8FWnyl!I z@m5^Pt4U*f3>o*JfBDk*1EvMic#weO;VUTY_Q%^nA$!s|LlthX3fFY8s&1vqW@$Wt zhzg;~FRO_R5a;2BDccABTU&t~#JPqwYEME&NJ6;%2l3$O&-yXET9hEJAHbIt4tR2y zU}GT0u(FH2g~C_&#-JoVxIKQ+nG#rkRZOJLM_hdFKgeQ8nx-;gEd*;T8o5>R&5_;a*cSO8 z44F6FG5u|R-3bG&0T-C5opWKD&QdKehB#k$;v7CQUrryHCF2HtO9uL4L0<>7EkxSd zKRSMt)?3G07P~g?b8Olun%dDD41Pkp!E!9Dx9Xf;Y)GWQ#SqvPFT@`LZF#gIF#VF8 zA#f$HHUu`Ff|wuhsXqk%%^O4DGy%uMi&@-tkNzez1a@e+Jwv-A+Lv!7pkv^%icz}?5oW@4V#Jc zd+PkjLIl>o&CDIa9F!h3H9Iu@8RCpgYhvPCyzeavuOui`|0@;yMsMP45m6G@6^d#u zXfeP}_US9LVN)OFPsMzr3*Q2=v9tVN8h@M=+>UKnQXRqOl#y9aL!*pKnk8L&x3 zzHdmI4_e*cso~yC)omgOHC2bH+7BN5`xI$kb2zdgJNb~wPSQaoqfnVfdpi~lcAdljU|OLyY3>I1HGpYeWBq! zmsrAb3e{mWR5^>e7d!{}0Duv@M5zH=JVDS$u}g`2Ay3Vw;!q#7t4D=%lBnQZ8;)XK zngdws114Bp1y|SM0wlf&;Gc5<2l{{u3=p%&T&s88F`s9YV95HQX(*71yV77e(wdoG z@@FDu7jrXM#!b7g72G+(=5{CW`3Us~gR-Jzb*S#UHV|48u7J2u-RHcRe>VY`OmIk& z&{Qodwug%Rc~H>?LI^NY+jZ|;2MYfJNAIYk>QVd}iBD~t;-V%=Of{iFeekd5QH-kk zNChE?Z7++T+}3@OY1k|^t9XhkzMFB@sy*ZtP}clfMsnQp47yf>@On%0#;rS6iBF|_gE z6C3EBSdFW0j@7JppNC@^W9VUZ*BxrZXoV%S?j`Z=z8yZ(2GA;cEEV3Gjy7IDqEZj2 z)IpSz%*KO@zt{Y1M#a1C(Cj)M74#E=ZqrH~98EtH)w2RG&DTzEqF`#y=375$EIK@D z;o!jjye3C`@YG`$Nwdt`Fx=C-J2gB;Mbe37O$(__TIj~DM4pB=yh+}P$J&zt>&{&3 zYqs5aL$j^+Op#Nh**G-UUl3SpgQzHL`XE9_T!C+oEwP$Py~Vp$6AeQ3*HJc2Q)jt8 zvHC*(WN1>pL9D(9pRx%m;2nZg0D`*l#~t}mnjoe+G1MdGGZFJ|<|lEDW$XO8o=ukY zMdEJAu*JLkPslYyx*D#gBxuwxGkr`%EEm0gFys&iB_N87liQRGR#u;vL2w zcv?fH2jc$WiHP*GYkYBE%^Tu=lYlvon!@gq&wMLH%Qd3wsSI5Qh^{K53sI+%t>L~2 z`tj-Ynu`C@dd*`*Zo^Ab7sIv9rwWQta!or-igiNQsGZ1PxZ&tqT=& zN|@XS`ktFnO81@Pb9xhzXDKD`z>m@|c{LxW=yFe zL2e--SJaiYv>+-8m&Jo;W2bZEABR^I{=w4dOdt6%0wNMNiTZucu_`ULt!(i?VT>m! zc7L~?f00hKC4wyyy@d;1?re#|45gNoIaTXggA4&Jn=e5!1UJ+M>@J?w@(k5ov@Gb@Fi;fAa2#vGb4rx9*48w^HP6 zjJCWVraO8Kx4+Wq&jPVq1(>Xm^ijfdHCXK^;czqyZh;SnjI_KT=980{g|t?dbwA9} z*tp*PFvT3Bjz;V>_e%y`;sH|zxPR&UVLlY*c;I{m%oNc=r=h2VL;V1nP7$sJKRUb8 z2a&x)+c?HOnRR!(D1c! z$}w;|Kp8&Obcs5}J!w#5mA)1WQ|w;9^uW&M^>AEVFL-tZas$tv!Geb6SDwQkaeCOX zdMHkimD4y>IKF{n?3ll^f=NT=R`Ec&8D6=5vIkV_RdO8!*xZ| zAhj|smNuifR&Lss0{J%G&}<1FZN5QIca z+-hd4;Nuzu+C`O;wIeHh8?zizNv0ks#3wv3Nq~6JWa_iJ_2pyIs zuQQ$;AB6#ujETe)-4p-OwvDrl_HnE{8Aw}KI7FE}=Q6ln+*8M$&qHD_xWvvEmV`s~ z+OFyG?inL3cwYr});ZiNbSn>0$G=YK4nq)}ahkpzM}xyJs%f#nhx&u^*vne6Mn|5C zAxxB*{psS=M+qJ*X?79a`@%({yYc zt&bd@#=RHI-M{!ID;Tb9Jda-_|Cb0Q$C|Y~bT>=6r{gWHP7dCkZZBZJL}oX($HjWb zy{@Zt--^i6`f0EQ9;Mt*_cA@fS=W|%K^VAzR@l`EdEQiPN?}F3s!-Bpk`fz;LXwvo z8`!%%c3xk%AFdkHjE`NaQB%xx{jFVGmOsBZTvWu_sDEo zRj#w__wnnMK|RrBePNyL?HRMC()qU&K6W&qvGL@8OkBo^ZM9bxf(cr%ztfUj&wZ?; zi+Y6aUr@iSx;XWE^qf~>;jWaca9&uj`ho!6{6f(*Ba$QR#&)iZ4Jn8&-AZJq!tV|u znS>Eu;k*_}-6Sx<&31{8Y1Sqi_Lv@en!3kCpPxQw`TcQGX#nqkiw0v8iu@K`m zc?PgNLR#v@u+GXtCgn#2~q-WQbvEzNqAp^cdO2YG36B zmwQsD46%;(EpYb$@Wq+`S%s#uNsQ%GHK{3=p+ec#$uRm*t5Y)T2^@K6Ed`z&C?W_j zuXK-i3zUpGgjTmX3_>n6?vh=xqOUcuEG(LH zz5UMq@1N@Ttra(9Rg)M$WW{wvA+f9ziwZ?zgdzMoe5r7%*nvKvpk|k7$xos9dFo)N z9p|)1on1Ft0^!o+zV_2#eyVVGWetL?!llWs8b0hh_wO=TZNJ)OdaQGO(werk#>28j z0}$Dk>2qJOMwiA`V`QvOvq>|ZTlb+l)|0uYe$TV(XwXk^N-Ih zjQ(w7Wyylj{jZRB*l%E=#=&attTYd7V7DQ$q6HQ4GW7ny&dEXEo$TbXf(h&A@cHwM z-#e7U&;5<4aQQJ7*Op+MMO;Z@{eC*$m$`=!J6&nPg`xTzxn(5VVCQ3E65lxcEkAFHN{XVvke?9oun}2;PV|a||fxY<{W{Nsc`AzIX6O+gKFCo2@u+LW`M}vGA z8d82Fh5UW}#mx9Loy%0(3sWxueBnzWd^+@?cmhclcvYb~-O-k~hFG8U$g)UkhUpQ% zFX!>y^vCmhNYB_#a953VI)#Y`T(1t2(CqzkfBh*fL|vr9-x@X8{R?V3%`KA1PZf%I z;FJwe8@mFvF^J+@l}&$I4K0s7ExlD48%JW!xMBQ*JLBNaIJh$o?u;Wu@@aJkNk(Pt z{891}xipR#*whi4S9nG}kp6$g7+}Zqk6_eGlG+wtS#S^mBHLf=Yr=g|x26fF@Q~Jo z>`WZTYjPx-@OB!OtYW^4^N_i+sSVgQ^qs&4bHhy&t|bUk8S8l{Mdh;+?jF!4xmPND zkJuq|;k1AlxzcU-s&tYzGluF0@hug;Got>}7(z!aFws7mu1vdh9mq!(iANXr|P2 zr^2j#Y4im$Q4q3_XF{FIYvOUb5Psb-kmuXgolfx|dB%cZ!w!?jiZYKn&c7mbWRdV# za1o_&w zSsqj2p6YmL>)L0n|6`SYypRE3^7wxR8D&tGtDslSvAFtXy5#BEk9C zQnA(;(s}+X&=r|~rm)R48$W!RmEt}jD&04?(z6719 z9N<;@s+IC8eeS57mR=&T4!>RL*CwnjS~@Db(#2Nk6~gwCHwDbGQeLH{xs_fiup4c9 z$~Pl3?7h2Rt1V5IWVLjORaz@-5wFtGR?4e%89kBJr}YB+!*5smL20X%UY=d)t5)fa z!uEy@v+$!<%B%E*+)8f}*uw(bvLLNFqSZ>RYo?7U?Sx zne2}4yS*R8DL#@m=Ogo9vIdA#bI#Ny54yeNU)VvAA7MS=!~n(>sa=)2orDAt1vR6( z<9nEn*%^@uYL3bHIxXXI<|Uytapv+bZuXsu7TE%V4@#T!x^`ffke*YQ0J@#=$yrF2{45Qdp&_b20tfSUmvAeiX&QCyT*6M);|* zNMBzut)tk>h|cnA6+`)j-p5Y?}&mEBuqueGxDYe`@jMM8Do zQW-DH0SwiBrWa>bWd`)5t9b8?R zU9Nk9fkqYlMg-==V>QW}*|3P|&&-A+6vd!1p4m`(0I!MXjTga_59j%Qo-rZ^^NdSW zWj^Qa#_r&ahRy;Y)u1B)@}*1%kez8Z$VP_F;KN}M`%UFeUR3E!Wu-b*%`!W-rZ$-3 zPU1Mh!fbbPpgCVGHGPF$p!E-?{F+ifBTc^K!JLmJ4%6NEgR9(u^Q6YGZBsSZH|pqk zt_^Zdf;p?)C(Nu{hpk$3eB+t?MDKT0Vp;3zqm|H!7Z7<63nVi8O-2&|k;~g+#P2O% z#g@F9ytpF7iR@G6749L9*%Ete|AM|aDm;SJrhoIPqr>%`{9$# zsfyS|>j_eDVRoO_bV+ufwYno4e}{;MZpy|@<)ZA0*fFd*b1rtE?GSbDzj5P8!59&Z z-D>w7a$YAMq}(D4bqvEdqR33&KdL^&k8m6)AZOmf^=HW`BH0U_6^)(QxiW?WzqBKg z$Y}WSFv1(%bKDZ5CuLqJGgNo15+J!!y)I&zkiqc;*Q2pTJ4jca&O3TLI z*S2|c9KTYUzGKzZag`xAWd0lUUZm+&jjh?_4|2|vgp=yGhpYati}mZ>{HmbbSLBj; zK0(dX*}q?<-}6R&t1jxG&d|e&er4nzEklRgcc`Y`=`(1e?zCf%_}{eoXtzG;phc*D zTbMV0g;DypXxWasDx3oE_7k4U3d)^lW|^oIFr(FM1!l%XBsBN)Zcef+bn_B>oIs>F z&HC_5;AhbX1@d}zhqQCH3~>tEo^Qq}&| zD>!(%c4gt0yViczHX66a?iFy$9L_}=jvyFEDTTf$cK3cy?xp>u%otvAq^MnI` zFFk*N9-?C~KUBA@gZP*3fa=ye;J$;?9e|hiH)Hy`21zUvfem;fx1hAJWr>&6ElVPyr82L5&9Um^c`@UM3j zQHF|il;IBgCD|=|e0k|;p*jV!Y?jhmuEM8fjF29LKPo(*pJDPQ3YsC5?5#h0A9%2Q z{$H)%&F9~C?q-4R~ljO#`Nyfp}B8ci!|i}2-7Pj&tUvbMc)FvG_N z5B{sBs8fqKBxFsb=(!TLzk2nkkSOO{;WUjJe`JtI^mqpQ{$TD z*3I{fb%#mdQ(bJl6C5aEG0HD=o)CYf+&`O@n&(SYnGywN5XLX(s&2A&DcG*L-~}r9 zA_ZI10-?HFjn{$WdeIaG07@(h{86Rzf-!PG9Tp8Kzt46VY&~K+gVI|xqBX+ z%x?&g@qFnCnTA~>YOk^cLvP_cJ$0bKV>lNpX1LqWQz5()lvdG+32vMJ2iOfTxQqV%gIG6Ip2PXWc`!X9P6Cy#q%yUCL0J|Bi{@ z6GAp;E4qTE*-=p?nU(}!JP?EOAau$XJYb$5$25z1evflp|>A!Czmrz$EKLP6ml{3zt@6WYqH<)hdhq zswLA(=NGq@Wra#-gTkwi(~i*Y(pPPi`W~tabr5T?r5^Iiv~Z=60M7vD*Wfl8@weG;MAal@x`tu%2thEqe8POM?8Jss8 z{0Uyd+dmwou32jAeHRG%^QE61V2Hexo!$b}FbV7<>O5O#7u6W+exT8`wt5>gsz^&- zp4^Z8B)S_)L-pU9+q25;`K;FuI+SBMCU2;2t^E>sK{V;?Ks4`F43$*%pr~^yCK{(u zwa-a$tJ2ZuG;O&%3TsFPubg1@jogRy@{U5$`j*_@j|cW?0N4jiU;W4+2SILv2@Hv% zo0SbFoXWXG>gveLr!}qPJI4rWV15>kknm zNppSF{&1ZO(M!j9h&-;(wcc6}*PnqDpX6URKJy;yt~^_)rlXGoJi9r zsE}k?q-mZ0_9dv)^roH;iZrd#-+fq`j5ICO<1Vt1qLHS#yePsV(QKB+o?8v^)!7z^ zQQSs)B2;&WIuYkIR3EqQ^p17D#_QUt`_i@j26g7xDOtB}VweP+{E`w0j)`*}iv#9n zzeN-@EzY>pi+N2f6;)2K_uf2vE_cr&o-+nbFGN`LsT0`SFq*S-2pBPFYC#}_W|U{p zdhWSqYx8UYPUo8VB3*aQ#>q5Q{atvZTSge+y4|1q*^pSXk>UV;n z&Gt&7!1!Cb`#$*GP0!;6dH!gsv@Wc4Ca@-p zE=mS$?q-6=4k>~zXN`|~CqviI{?Dmw8{1Z2mH4yqBm71W#WOGolmPfI$QMomu$m7- zb{8^>du74R_u+;aP@fFY)7e0G`#`kZL)N4kK~}$Z3f4mSPmJJ9&6fz+?62ye zC>Z4f_Q%GWgFP)kK9c~*F~&?!_bo!M@rMfCPag9#3Lj>eBu3eQFh0Q}^ku%F%+lwgHAHCm>wBG_th?ZD} zB7K8J7ragH9)W?aW&g*+kNY5njKpR;_YxPn*FfomcDugVWg>0TIm3a7! z7RZ*NpAo*jpM z79P75vZX5oQ!tX+`>IV2$w~3>Z~~;c7e9ZuhkSb-(ZveDN=@D( z#63`~aa@f~=A1D~vh5cTntMIHML0hb79PpKC0?jhO0FB$0B5AWbtBLksdYuu^d;2} z7eMN7J#UrH$HWiU5j|WJaW*SxIKcTqq~jo!6)1dI#hgHvOJB|7PWX}T3Le-3U#0eO z8ME|1LI4*R;rlO8$jXj2yr__R$*)|kN*M{UznWFg$f@}Q^V>tD=QR9VbH%)`;ce9U zF>#W)vw|nTfE62oe5Z-da{f*v^z&;jVioJw>gT87e!`8E;85lfp!=_M-d->5DstZ=Z54i;fP`JWAd{G^fJ zDJnkxn7Bj5ONu8UE)nM)vQ12+LbtvmrBYIS+3xzjgkTUa2f-Zg{9C(Ji6!3eLGG-s zfAdOFcAc<)Vc2&Bd*Vn?hw297#UPkR^pOQ%#>30|Vmy%J85k?`6XtvSY>Ln1)iT1q zLNO^Ltovs?z@vAw^C08Vj%SvCt368 z>>StGd8Kw;ymT6cYNk4iDyeIHx~@vEE@D!nnMbK;qI@+>;tj79*09lSNVg5Iw5xF5 ztY+udYY2F|)M{_8FiCokToIpuej;EwzO@+8rA531@v}4`+rK`hyZT`xO))GtHDfti zSn7Q&90oXs1&=S4Nn=~s&8HDhmUgp*nyZ%r0<2qKj`U#iWEX{U%zN~xZ z^bZX4>qJ-yC)nC5cuC;v-86*+=`b8+@=}d%3mR+_nRlV^AE@72MDQ$5QpI?6(tBz( z05_}e>T0d`S9sB7?VA-Js>fq8^1{4!e2P~4>w#j^#4jXiN^-c?;{zUR|%(! zxaqzbHsH3a9x`Qj$lKW??-inqS>){^@^le7+i>p(S7hFB%7gI%Fv1Lz8*^^Y^Tbzo66f zbJV@}S7X~@5Y$CY{EGS`^KOPjXiMC}8^8Qm<~LqTk%f_Yh2p@Y{1&SF0v`H)7=p85 zkIej#Jr|tG#+@udpCxo(TSfN@Q%@dIMv-0Az1~V7I?HoUSYo&W9YU-X#s6!|#L@$I zHpM0l|Ib;T`bX6$u{5Lpl~@`uF#K}O08(mVVn|{8?v+9 z7nzSXSze(c-&>J){33(`#k0oUG8X}A58ixTjwe0q1RmrUg8v9ocw;wc4V8yS?Fg?@ z?VMu^H!Lix+09v4wCj-_(iiN7ru}nQyI^nHPX&=s`9~NsEJmDEXv!w=!|p07yh)zG z+XI0w*i~x?k3*~9xt$v{OGM_a7fb(2OPpw7xwCL#qFtnRU0HRsizV2NMB?G2*%Y3f3uP`|e5ppAeB!7Tew5C?5 zHS$<;Oj`%ZOIv_C!3j1$zvmt=akPBinu5r@?WjT7HgX%ARj}>RV^(FXxrZp#I&aM| zGH-jzHGBtGk(}|R;NSgH*hbEXoW4klva2DL9K3r7OU4{0Wu{M5#LL2xByJEZu zBVA<9Ul|kMsF#IUUcu-0_|9K7;*oej{1KIj<@OZ3QJCX_Zaw&uwVkYu-aUkYdDxqv z+^h%{AXtRLfxB}Njhs7P(mEtsySZKUSQ&A6QHuoW1P=u@a&K}K5b;$e}ICJ27UL}JqJE%TX9Mjpz*Osr{5)cFa1Pho-yj@eOd2_}dl zSzBn=W|_wEz=!^)9yIUodiI+HlhAn49hwt#*nx89BE@BJIF`G+y{>+#{+Q=fct6l< z@%~a18;L?Sr(vvC7k~(M(wB1hj_kc?T!3n-g@>CQQwk%sbt*hjs_-`Hg==A*iHu8r4YI3xZ$tzTMoeISR z3H^!T&f5N|_T|&(*YV|drBZp@q)5XWC5zKbo{EhdAv2wAgDeM=NTvN#=|rl_B^v(3 zl=gq4&eCLL?w1m%5Rt%SC+xA$)R`$3{DQk4EV&F`f{PfL-I*?Q=jy1JJRII=F4No= z)!a7BrnNI8BYi6+ldg(AURhLdf?41MBrfe1br$w{&3V7y^l7xYx)X?M7x#^fJPqeV zi$nDBDB0{5c(ZUakz`DGEcF`BEiazjn>_682kWSp4T&O51!4`Iqt3)`*vd7B&?9eb zYr{EV7H@c^IXDdGhiN6nkD@pw8+QOh;xlYqbG=FeyHTq86k>$;0aratd`xGGmsm-4 zpb@aC7X<9=6Y!v6P_p>!bu>rmK4kwFuMx~HK8$((N?T4;IzLs$&+mpKB|u_0ESQ&! zV{`lxnO-GZf6*bTfFq+)05ooNzLwda$IA7Ny4MFUSd(kOT_um4)RLBC*u6bJ}Dss9((lu?7akx< zN$c7jf~ITFZ6`_UITkrfh0Cl9HquQQUHbu?{$J9yovgoeIq&J(diu?D?NnCk=1%6# z)3whib0{8cYaO$bbnTG8{a1DEmio`zn^Wn0qs=)a@7HP7*>>mXlscBt3U##QSQgW# z6cSDDAqCs1=?iE}tVgL-#;0^{Ts?I^<%5M-la!9QgxSmdI$nMEYZ@w{?>%#X)K z>Dfk{!VysGj6el?dxn;R8=LM^`4sW+YqmT=l`}ht*3y0||Afl#Y2}ed&MT%!^;taJ z15ot{njBraR8*zH{j8YjJ5~SleiVO3#Xm7l>ZZwA>+}e}>Q|fIDSbyk&k0C*Q%x)M zWKpkFdoBzA+S{Bn3Els`;F))j40-;?pxioav<*7HcpG#uX|}XM$Id9x*_;)${5A8w zSAd6>ABELM%U5XyLf+LQ?IGtqh)C|JeJ<{K>={sY4;(FRTElnRwI?KRL4C;SeG5Y- zGFwuL)BDIu)W=bfUJ)Ns=$*SW1#f+9Z};A}$w}4W9M-Mym%XIGWekEX$t(8USs8mS z#Nhsq`sNjYu;)J6_P?ZWM$?(UPv88!Pqw~!sKE5i51Yl&p1-!0zFBR8Auj&^&^LF} zr!5DVY`elrU*CkZP|9|z(bKE`bn_qe&DQ%ccm{~lE$N$+sf1BiEo+MHglg>_nI%cnl%f0au4gt zv!!pwE^CS7H)i}Tt>>gqhVyqIb0%EWxd1Dt`XIA#Hkw;DxlqTXOvb{gDdgI8SvaBk z?#xJy`&ThKrUGO}PvgfBoVdlx1i!?H_5G!9nO`iK=BBOrhWhc6X}bTBS4*b3bQ4nv z>jtG`cwkx7O9y{qvp0I3z+ViPCDS|tF1(yUhN<~@r9on;$YQz%!z%YF5`{faCsYS7 zc{bx@DmbeLU?%+f3lB${aq_BXoZQP7fAO+YV?r(2(aPmGrQyb;e%T}=MeF9j^x06( z;<-ALZcDofq20?pANEksHN67!~3==XLm79eNY{}4Umyxl?0tIoDYttkxk2=Hg5kH_Jwj9Z=t4s@9+O1=U zVW{qOnhl0-wsBSq(A+Z`n~V)ogKsgpx4WxmG-pxv{@EmTH10s3<2aRS8H9Fw*IGBX zJ$V(j=?p4IneE(BVjI30v)q)~1uQc*cA}F2lCj55-Y!o+asXPh|96z<|9woT z0ekEKV1G+LX8C?=VC?VHjbjzY$oPKUQsPMQ1>dWKdQM=tr^4mN-yGfePs!H*PMmE! ztwgt~8_$&7NH^C0h;BSty>7bETmJ|KtV=JDZajWbOB^kG)9=VkoGq{ay!Gxp{iwY% zStn=qFeQnt0{7(njm2^wsR&!B{uT|D7a=k+g@Ml}I~}0_2dc47U$M9-WD&PQMcjHR z{zK{sqh_j%H14;T=OKHm5A8*I-@pZFtXJ6yrbdL=HCoQq$lr1?)Vk#@ zprRRH$f}NqZ?iQX5MK;cjdws!a-5-D<1}SG@L%WZuvAGav9g*U6yUMM zosNxn3k{i9xiNw{bOZu?5s-dV?aIdcfP@z}YEj~Mhk3S;ZlQxlcEn7J%$As;IT8z6 zXpVtzT9BRqDn}{k@I`4>a)mf6pfYwD+7&rr1G3x1;Rw0fHQ##9*EZxIpJeIBJ*;yA zC!Rx-y!2ybHgJ4FfzB+rh`#tc8<`2kb7+AZRoo&t9jk}jWYUeJB*y6Pcx`0mpaPk; z#4mW7!4s|ab= zJPfXq=d6o~i?9Ax&zXyf$sX+lq<=B7wQzUgo@%&rcYtFr)H}4CBV}krpg%D`+s2E9 z)h~GBuQ)Vp=n4#meOW9&l2>E-TVKQSArpO;FX0WA?bjm(X~_6+Zn{yg~mX0*;5TqpD0#&y)vgQ_~}7b&##tpt1b;?=4e`y*97d%54ZQM^%A7Xin^ud_nnE-_(T$M!o| zZ&eLaRU^Er4sWii5{_6^C0SLWAP!7db&TX-V7jVePY$;8stQrqJ(a4ImV>$}i`KuH zuCGG%xyO)_$*L3jy5Vbq$>2ys3>L(zKq$&zrYqezHntm1NNiLgqlhDDdq{n8KP?ef z=495o%9J19tAg`=y*JkJ_RxwJ(#CS0CXU?k+knbM8V4$3d8$TL{dB1{&cYm_40*eI z#mmJL1`gbtZ9n&CUH(>Yy9L`mp5a^O9u)VqNhbEzj>dCog0VNTRT+4-=PW06GLL=!?^sQx01|HiQy8qYr3zxb`!SAtoW)fYADi~jtsHf%$#4-7{4E3m35 zKnzpryryyVHXQ7a&U?EecJ&*?#VcavZ;)WW(tSFMH=fi@6W)Ixr2(IRL}0!O;Ply& zo|EZnUk&!GfJ$Et_N-x>P?j28!8xBmni@nI7vGNWfvogNd9~K7*4l__wGFt<$EZms zPB4)R970UeA8#ik&Nc{c*TBe(x8mz~wefb8hIZsKf4uefhV}&lW}i8Q-Qm+R%A`v} zP+H_^XyAH{cc20hei-^C;ga8zI5Po1Z*6r|Ms!(8&KF&8($w5TTI9eU?lJJzn}1vj zL=|Y2VHhc%o4uYQe~wvJ;=+97h9`Sc;B15~niWGHRgL1z@Y0qF7#h2LK^b~|RAq@9 zs%yWS5x#Ak441m#I2e~^%R6u8(qp_Dm!e<6iCwT;lbrDoJc2j0k|W@F_-$#dUQ@HU zq(cQ7-|@KgbeUB)6$;W^8j|J`M-Tf0ycI5GCg_#!o>#TXAdfr#EWOg*mO@=K^*N>wX0-bE|Qpp~lT?EWXP zvwRPrOG8+w_V!RYLS?=b1^~-9%3jz`B8x92S12CtEMG+4&A$@5>?>u(VbH!HNSq;| zSN`Gmncg%estRCw2&P{v1H)rpV%#5$Ynv@}WfsU0NVE-yOSf(28gBO4yc*Z~CE(1q z<9x0iz#F8N3z)p&4g6Mkb=Gj$QB6JCYwAqsU_g$i8R_A0VtP0XW>bqd-!UA1l)sl_ zuWAdd!)~BeZdWXkRuqPf2Wj`V=5Dn)(a;Xm4;>9m7<|hb5{bZ*b858E979Y#HsQ*w-nVKKljt zMC}^iyX5e_XS+1t+sb0O^%9@&-+5~2Q_ph!tUVUXEHs7R)GiHLp=&(d<9iRZfD$Nn zS|=GXFH{4%Z-!^OPimTZ7-i!X*6XW)UX$~B^RglJ8uZ|69SHhkEF0W)NBvC z^14gI&SLB&kFl$)75|5}FM+eM`v13G#&QkvAPiIXWrQ(>X==tg!`R81eG6q9Lb8r> zT~}0=LXkp+v?z>miR`-&Q(5B~Tcwh;-2eOiIp?{%zP`WT|JUo4x#xL4`{#2$=X1{U zJm;KDhSElL1dH<2c<6q@ckylspOhhs7gdOJl<>uXit;nw z{u3Y|O2FzY3yRud`0L+h&^I+DOR7Z88UwPR>GnHLt#C{M$lg)pd7V?={6 z<8c{DmXZsx+#XjG@3Le>6ERyMwuK(S!}9a=kIQDFfCuC8f9fD>dqEA$M29D?(G0ud znBPvCd2R#_%Npi7VcsE3(1O7xmJ8UI_PjR|m=ovVQH08gqTBDpo&s#11n)7b!h5=q z6L;`~QOJ>}EufwNlz(nvb+MlCE?a)iTw%YvS`7zyGEHmryhQiZBf5MI@&SS+OnO;- zj_7*+OVrGKMBE{W#u!1`%~8P^4>KWXBZWa`enKrJRLDaT94UckJ1Q5(K;9fm-mc2* zxh#24gLB5i&?Ysvs68Vksr+2ZE$TJp@zuL@hz6Te0^eYA5Ij z)2>533)6P~Lz}i1MXf+lqe*KeX(_9wT?{K~Q-4tf@gX8UD~QIEf}}*P5Fly=LNyN~ zYAfeg2uFNAXI{WS=XIEbQw))c0V%Yf28Um(sv!Q^rBgi&@aO6sO>pML{sQtJ3Y8cP50qZQBgylDMk=ax->)~bAos`BZW+lD@ zv#BA>dJv?8#jH+vW-Ki~#2S@%M2Z5hO62v^t1>87p(%%vR0K(3{2BDUpIUPJS>DdB zBbrw`L#JXJ#yj8Y-XS2v39?IpRK@@$ASVJqMi69$fXG29c9kI?;Uz8%M`o!Q+(-L7M_JgE?1_rjghCf^o{+f7x5Blk{va>FJvE6aofWNRJ*>vbmtc-Yf(RA&bKh$ z>E0wNRe|O@haj62$WVZ^a_*Fg!Eh@&gwR|K$eqLx>RSBdip3`~Q+Wb>_TWfR?nSVL@Mqb2V#SDhDeiZ#Y-_`8OTTHIpGxpNfEpyn;CgDPUCks+X;D9~ilEqIYLHp@GE z3C^EPGwV?JnvOY=W`x*gnrS&mAz1n#kCc87Jz8s2&zlq#> z73p(?fBGb^M&uRc$LlNdic`E!oC2@J5MH|!uOb$&o2SC@QagsK{5d!ppLDqFoPU|? zU7}bG8uTQY?Ww8qXO+|5@Fa_VF(66l;t7Hz#~Sqd!;Xkj{AXmY*G+^8N* z{fWh4HI5@u`l2!JIGU1N8`7=6_0Z8+6D^M81a=u)xz3z_2(6=M(KTs2Q;FjcEyASN z=b!W1Qwm!mp|HIQwCn-ZX(k!AW!Wqm-f4qE(JVGwm9ZN5I)Up081Zh7Jbg?QT z+~DmJydAQTuaoJS6J8-AGX&=+;#{Z({&=qAG2VxR0*U@cfb9eb8tNBNz>!XPTnPP6 zxHkmOXvs)j(4D;akOQTTfZQR-SOroQAgJSHfUT*bLPOmpR9irWW+BO-*x1XLL5os| z>$5B&{vvL1#bG4^)GQhz#NPz@xvIqFbbwewtU9SPsEFzz)P6vP2!XL))_M+^12Fgo zDwwk!u;vR^;3{vZLxM*;|Ma;^=H9kA(;KkwAOlLk<~;8ouraq#qe#FmKL%x+bkhO* z8d?b0uUWyki~&G4yGXW|hwnu*YB69-Ls+EGZ^RU~Jy<}{z2o3@&FoiR^HsS&pef8Q zk=d!Pn%POkY&U^j##|tq*9Ph+^5D!;XWWuMB#JTkDb8hSCRY`@z}D8s*M3X$?T=+x zi!Ziu?}VoC?SCA!ds%#+LJLYhMqrn5guQY!`06o&r9egSRUFHKBTJZ4ifI*p9}w7O>;P}`p8;elsenvBx??eo)=XDa7EK5G zm|jEOElh`C8PsBmoZ1~tVVdhC2#>Lt{(3@~CJ@+VtYgvc0Moz+y5iG^Y1!i7r}x;o zif?c9HxZG_5)}#YTO~?_2fE2FK13WB%~K_NSH%e$juExtrc_6*R#>-oB-fXvT@+dq z@$lD?52B7K;M<~|7n}}X>e(Q7^#Uh678<3C@I8pU1&{j9TAs;rdTfG8(1g4vv${AWEr@t z27z5h6Cj&yFgw%klJ`G;hr8;sKTM=$>cDm~w}gPhgkvFp$mp zm^(poZq}D*y%CW_sbVRm{N}Hc17yUYMm8_5i@4`1Qsm%~E6LR^ zr^Q@Mn@70Gfa5Y!<{8cg&M}xG6`5Cg zyEktKuOPvUSV5|ASTrXF`KNmM&nIG6;g79h_-X=rIp0lCFaIQtprP>y1(R0%K2Au-?q?m_xV4yVo|$;XW6@ z3v!X^ljsl>-q=%ETw}dPn>|39HrpZQ061G7_Ss@tydC*J^QjgK$mzC%kk zkxh0MO?EZHn-18MB`LzWXf;<097Xv;NNy=eBOL=u@m-{WRYBx)3^nS=Q+bs3BSxdh z8C7K&-8K!2Hn3=9dI7fO)6n6#lwDbFQzSg0`C%XZ>w?6l>8 z5-B`T0S{;LA?XBfI;;*NP!DGs$~qGqSx4N*hck60oeVwVjSn~Cqo$WrXL4%rki;F* zllhJe5V~d(S-KJ8hv?AIll;h&Iq>K%az;^p(gvf!OxZU19k&b1^BIp&pA^zq4lY>V zi{@~V(O&oBVrsbPfY~{E@fwVE=3&fnbpByIJB3v0lgdR)Bc>0ePC6U(AQ7~5*&OcE8 z^W`yWsP6XJeu^koLaBN~fKaMlA=qYssds^RG;ngX&UvWr)olDH1e;2l)b1TTEl@mu zRNActdT23(At%`H5RZ8j$3fE?6KD+y=x7OX|99`Pujm1xT_q+Ha-NV%+N8KG>4FSnl#%BUPys21bC=bpm$xL(63-9ktjHX@!wBqH<}{! zp~Da?$r5@SS`d0Ufn7#>Ae)_@4iGx8SBk<)ilQR4Z7YWyHDZXG{e& zh37j*K=)u9ZK&7L0#6%(@tlt<80RsELXE6<&b={))^cI3UiqhpV!SAd9kfYB?^9T0 zZ1oft85;$|0hO`&%RDDVxA##;l9yI7MJtuGLZ&|wV8Lq|PNO9R)&Y!l5lJP>_KBM$ z?ioXf`x2m>{bgCw4Xo~>Nm7?GJrhBOvsb!$Y82YaYm*%BKc4iX6cOW z}^TVycc@wY(UEuaV@c`SLri^i9j;rIeW}K^?wxiX|+0-_+Q+Hz$Ox z3vR0S7Rz{oJ*Y0gkpi;!Vq6GTKXw~>=zRW@J_>nXzrs2h-uJ!2dK6hmB52$(sIGGt zw)uMoO^Kk@$X2Gam5!h{Rqkp@V3+Yakj=L-sX;R0_7YmA$F)pxkO_UHFvCsH>(O0= z+cebA7B}?6(P#>{eS1JL%Hp;KEyQal0%KkeWU~&q`DaSa@(IoI%aYzC`N}ToP2gh5 zm8gN10!XLGuLDvfUR9C;1@-TqAUh{(+&;h!wsUAWi{)S6#sT$(G**~wF~z6xuy2ZT(n@T@dS1mSJ}61n2G6;tURLr z^J`d1QWY=;mPAI+0BDuH??HwxAJ=${W4kTA%PELKfQa3TWY38Pi)SRy&O`|5!ogNy z*!_j^%47T{p72(uwID}EBeG8;`(CBRKqduOQBn!rQ#7v^m`N*Hne@PZX!m;yt@&28 zpm{!(NzFsJR}eEZo&F;gtFdGiE8lS$8-QS~%eI4TvMwtEjU$vDP@(FNWRk<*ZwIUFNmlV zpHJm?q_YENZW*C`g$MDGfG3eclJtz=wOi?D$nJslx6>F2F};}`3pRLzXV*?&X4izL zk+4~U;TCw*1v0w_{R8jU)u!8>3GXvU;Cy-*8kv3ZR%Z71zVc=E^Mi5YUo(4^DRc;R zOT)K_$n5JNPbf5r zB7#YsxE5JcJozTJYp50=tY6KsIALK_flMx^e~G zs2RJ_QnD*0NsVI-zAZ`4t_+D%vBd@kAvt@+NZi5k;}-r^;|KOdk9!v+*tzj}i}dV_ z<|Ow8$t^QNjjl_+g#d!oC3zEpJmMeNdkPPmOpLve7T(BLqFM+v*?!!Z^KHN>s%VdUt zQMM(TqWWFt@=DFL>ep2+k0CIgOS2C*=pfO_Q8q*i;e3IdGan#l<7?oz;xZ_D)rjrV ztHL8)BGODC1*;D6JHuUC{C81?iRTsvER7`0ww6YIK_z7lY^ufo0WEm$Ikhx0h$ZL* zOn!8c5MGkYl;odcVz}>EU8tep;RBj;pM$ujV+ISQ66ynGM^@UlVooeCE3uFYR@f6CF(QDb_r`Si$Ql7 z3$r8ly}gOK@BMAQ-1pwoxbd&Kuf_{>&p8@6PIBKTkf;?-n)^@553fLGXXI1KPfPw2 zC9em`5kn7%WYYUrqY9K5dJ+S)&y%*=XiDnT!PZu#Df~V~I3c z6HQ^+F9T%1Pt5Dcz=EYAW0&2Lx%% z2rEe4=n-Zvi`&Plf3zns=B+?BONegr1SvA3Gr0|>=RQ`?`e*uB8K@0~)iC_@vPVRyRLPWp?2wt;mLv8C}S16qz*vvrWhc$Uu>s6wF|~ zpJ=2+Rpvy3MTtzPIg)Vzwk%R%O&CkVc(5@J->c!XwQ+cV2`?O~=Nt0vY*PT+h6qt0 zVr-M*!`4NvG)?BWx_|@U46EZss?N5U96!v@&K9&hpx&bJ9i^(LZMti7_I4W+7_f~; z&c0Wz!;Q@FlvF+%H*RfYl{I^_B?6bbp7u8Vh4(QOf#Q*0z;P)c_PU1g8d?$Cn!cubJ*dj&O+Zgqj?FWlQl6&)5UG-B2fiD5R zi>AsCpTnsu6RiAz79#m20=tae=sxCV%w%)|q)0<4Qg4d%9YuN>$w5|pQEknIKU9TT zRY9BuMC>-1LyCv2a#IH3?1JnFLDmTNleSJ?bSWzCG19;AS?3%cWMuTADAy@UQOQ$b zt#ioiztQ`e6Sa7csC|i=yCYCfLKGfreaK9m=nY-2^dQ0o%0{Rmeny;nS|!GTFA-?$WLbN$F}4feJm8_VRyyC#M8DQ=Y_OHw-eCB)+G zNgMF8O8V2{rSV1Zv%Rpy!zAo@n**mTJMD+y4G8`irWO$V2%Zfk@=*C9gMYxGw8SY7>_T7PwK#`R=pHn0LvZ( zMsg9Y%gYFh{x4Hoe#1zb;47|Y`_=c03@hr`X5@h@Ihst>edr!6!QLdn^i zh#vzH6$3Zx=d&hkMxZcLoc{#(H?DZ%u;W4a92M(hugmF;JilyW#kM#ip^4&#d}Zqa z7t7hqd_GhrIX*kmh2D=#xp1ais-n74c~6n)ThujP*yDOCr#TUGPzW{iO*Gi|VhZDF%;_6O%a1IcLkR5;&bI6}v?&qP}4s z$f9zN8dJij zVL{f>l_0l;k{tyY=@o&8!%#%>)5B|c@xlupdyHpQPoc2!aoKdL^Cq{+7>q0Uy6sCO zn)tZ)A*Fn(iQgyI^EbC?unwf_2P_^)7wH%dSu=*Q*WF|^A4N0sJ^m_;U%^u^nAW_5 zIU%|+R%z@uTEb=f4U_id>Hp-!Zt~NStGI74_UYV>Uy)7rNXq&Z0%Wcw)r}A_b18ql zk6#&s$#^%Kuu%4LT$xl6bk_nLB%T5Zzq7VJB9WPZz4jdTvKhy33epA8mIeV3F%%$| zN|r7CxsUZC#(9k8v==+ZP+1T(&Wkr8W-)Wl)6^`jpvUNei`gvzkU3Fg)2n(+PRIqj zPJo1V-+$vbCa>vqQF=|+SAU@urh)nmOlV@L5h1i#0 zdPP}Dzhl@xa&1qPh~ zNJg8$5JObTIvNq<@3t}a%)dm)8`&+DFbTZJ6);;Ye>u2OnQa^$B^RILFGuremDYk^ zb->(lGNoWU^8X@DjZ4Q|8RAtyLOKbju;~bXYU60r~yAJq<-D3#*Ah0Np zobe2G$9JE25jwjYq2p~&K)^ABs8hf;51qW?-hm80ajCcx_a|JZth`TIbAX;{J{BNr zu(AdnnpdmI<<^h*Ta0wpM@TL8KaR@X%#ek-=v=BLC8GmwN zpUe1oIfBVNn0#>lWU`m1m9_993byn>U6ty*$O^F;A6nu?4eUd^Ho$&k@?|!nIjUkB za{_$_=VYrmk0*OR{s}HD85Ldlq6$6~2a;kh$k}}e&fBmoo;71NEf7fU zHlSeR{9%z{xDNsMN#TKLMG(jfz(Hd*B$&SGhhEolTCh=91!DbRZIdF_Phru0_`fr-fIF{txnd-cY<1v~#f1R->tznX9U$QH1 z1O|mB4kIUsrS$tU*;x+-KAyu41j&Ke2W((;s-rbd$;b=}!v zQq}PTGdFeAt(_tu{++hmLJo6shkZS%I1=6vVxF{0YW<+}dUhSG+@ptm{yxX~@lPgg z*+YryV9@ax4j6#U3u7~iq%FI6qm+zB`_0QSiVX(U4f@vKG*HNhVV{Vprq=2-7I#Fe z+JRaIdJN)0<=R3E%E3qu+bocSRu`o@@TAoct;BrEpMp^@ z*x<@10D%TA#C$Q|pqcF!=dM+*(z@-VZkQZ{$$qnd=w{!6H8#DVwmNBxK$I2;`zFdb z8Zxf;m+`gLl+grNhhU23w^9H{OfQjx2L!V|XZJsB{-P=Z#tY1Th!SiT(Te#*yPmY= z0BPKg=e5>m}X_Hao{PIF0o>w=*~>iPU%o;>xQn2k~i+$M|xU_#9_7 z9s`eSiNTo~nhZw=L@sOFgpp!<@B{vl99`RdeTa9w>YB9WYf!-AsCz$_4DurOL*A4R zpDXY2ZX|lv8mM(`P^x3~YW%?9jE(eQIoJvhMP;OhN-5Zq)-hH#G8((yJ7KnGjFirI ziAwd+rPa-MX}E7lpd#cfNjVkRWq^t13BIST*Xr>7HRQ=?i5vWJG>*O&ivja3(8=II zeo0$a15x&{O4z#()gvkZm;HH^4M_4lVzU1T%+#|~(!>kXazZ^%z`*GAZpA53N}cD2 zD*Gk%N?@EefXgPxi=|d#*pAl$UZE`)&XRp2j}FhhbtF1R(|7fc;a^x7>@VCvqThN|F{(P6vcGT=%4FGJ zxITV(_ZM#Yo^ln=#|1%|3png6K@0l}|M)TfV2RF#bbGA=_7#9;@F`x&loWc{Y+X$u z^M#PVC0EJ5e<&2Lzs2C4!jc42CGV;28{Q!T>xD7J@WRVKdoaIpKlv2;+&H2Kz4r^H zXRiPPE8r~DTG$+_x^-~xLs()hB8#)wCGide$FKO!MCJe=DSoFx=rP?u>W$UV28VKE zds3Vt*~HZph_)rmsWgr`!g+Z3BnGvxRF*v|VsOHl$L8!>6qsMqM9x?Vq7XVogl$rT%Qp?j1}}= zL}x`!bkx0FN})&L9EDZvdppTJ3S7g#9v;?Q_ei0)F%O{B$OD$t*NP=O zzq(ch%xZyIk~;y6S|M?}>@Pu>q>ba4Af2boZ9^qZu+U^lc62&rN1>VG>>i!s9Et=x zx_*lDVv_&4SFF}ih6SHjhO{9R7pZHC}b$>9g1g`VJ;tGA(m< zi%xbs=ghW{w3Yx!Cq^|3Pgn$?tA!-aNxkfA+0rGP}$9~Lu~kQ>{?`65Cw?$ zRN5iU(Q%jy&9+$8Le*4Ya|YvQl|+Cgt#vf*ujGL9V=*#tL5gK02-^p+t*F|Hf(f#B zUkwtC#Dl(oh&h5~%*|hb_O;e2)BnkphMJ=(kEX3kNT>Y`kcN!MFmog+9!*=0cU-ne zi#o`VtB~{gzLSvl_kf(VaS8&$`~>sh*lpP-!F}LBzw>G75BMoQYWY%( zL4DOm!1mYS2#!JRtubi2C~Bl~ftkYZ2Q{>Xb34F#rR{p!0%ptqb!c z=5+AY??~F{w5iUSiy##^F>fE`8H#J+V3_`4Xwm{n51M45THSmF$|Y@_N_8#{CV!kn z@3fgq0Kt?XlPH-PeO7S_C}Nar8xY+G4kUKKh#MVyEY-O^88eJhPJ3lkom@iPW}UYe zFURf0Zh&n4wma;3r7D%v_L6ruE&{R$4-7ljX?w?Dbv3L)cPHs8+J)okT>Zmc#mk!*?*MeM#DQ50Z8H{A$#zAO9oTW&X&cKXERG`!@bsp-tQ%N>I`ORnlrsBMRvwzD{mS;)@JtA!xZQY3ux}$w|i8D9&EHT7q zV_EuWpKX=-o#mzfxl#dFL}YY$ zY(Ij@F_~h?puR+lxIXCGjxhb@*85@mO9jjxq`w@)eeJri{pB4AC6>YegZ?s~UETR_ z{?fKjr4(WN%LLxhwy!L*-mmT1AA;i<=glLY$D-y9jOXSO&;P*B4tp0C$p0ap{SwO5 zH}5l+rGEzIlQCl4f3wg3BA(~6JcmtjdR|ZtD&ZH;LkQ)~I{zu2gYAhWAK3E=;_tVxq7&%v#;X6Ie>&__aQ9yRZi(^0&*x1S{+B)v@^{=K;{X5lcgw2QNP%V6 zfLAzmwt9;h0+E1oNrHOTUz|khY&DKh{~;3YdwggfGCpv`kntg4#1PT{n-N1hI>6tE zlg6(F$73B{xko%20_}~*y#E4v^;L116^~hL-h--JfmTK6vZz^qFHpbG4bD%|60f)3 z3657)G`2?WbJ)Me-Ei^h7pF^Kr_lE?2nNOHeAW5>rCz*ue%G<~D5XQJMTf-NT-IGW z)`}47Kg1eceBbfL>O)GY|1Oq-?XSk$PZkH;UyZl5-lY9s$K7!D_pcxQd{IP$JcdpD`2Ra!Xipu0HsQzHW^edBwUSWx;VIQ2!`rhbXawe8WzTZ3q{E&_4)+*u zTk3k;&z{@o-DhlvvF8TWL;pwd{U7V`akN_4`sGn-s3X5Uq5hZl9D=MJ&Ym~H$6-%p zPQQP9j-2~Hx90%y#s5)!rgK>?tUdGk*|R61{>S!I^}&LWe5>k%S{M->_Hp;fw^o1m zi_J=}{1>(i6Q73o;{V8=>$y4`whCy*np(%_ELlOm-#Lr__+jrQ53~}d%%w*#1q^#U z`ZOm^Buf`{unHAF2Th!dg^99keTb!>QnPW%5!DXE1>S~%@q5fzKO=37Mx zY5S4WEG)kr1-;|5aQ!7-7c7UZ7~|vjZ^~@@{Tt67wQiwOmHeAL^*Y}N!Q-h{ow?MT zG*~!#3Pe1{YL`&2wnnJqy*_*o4#4xXeSmTE;n) z&l1@VyskO-7S6UFj4HgF20Pmqz07AwwvQbEaT@#J0a?ODrC3X18a~6ha7u%;`I=5C zr9pAvY8{Izi0aINwEt~`9hF0a=D^?8s_cFe9g1$xnbMRrU&E( z-(+#xN{hqsOo)0?b%d-Hw@nzgTzYoeI=Iv=7S7L$AH*CLl@3o^I^-7}3>QK`IkcsS zhNI8earo?5BtXY`0IIH&UZpzDRaz9%g>|T3w_&GnwaDo)_RbWKey|#NG~XP2OAg^? zf#IgS0D|!@Bbs2m^3wt0G!|*Gsm{0QK6PgL)am39nmw%uZYVU3t>~RfohANxpr^Jk z`wm`%v!9iYrPL|&U#WvfWOrW{))g4nRL5OP!lvL$IlW<162Cph$4c+bRyJDzKro*m zVQVWW@nZi=X&%E!a2n4^ubQpm1F!u~q2Ny2DN#n=O|r#{pX7}t+aT@h!GI~KUDSIM zzQdE?V9+GcqKFIzO*Q>H8NVxOvnJwq9f?AQkkj^}zE0CS#7cPLg5Mi73_8{srGE$J z9MNCCLN*$&uuNagKaz%uFe+^oh4%eLLuLA9uTi*vizMuHWplOoi&>cA(ah)}rq6 z6E!zP-6*zGqW+3;>;6T}OfE3Lu9O`U(|DP?k5DQT=g*gk=QHsO;V zDmHeC*+Y4k0U_UN|&>z zs^9eSA`Jr{|E8or$q1#P&lDHwd!jEZ!`1Wm@ppcPD+I$$7RJhO88Q<5n~y_+d=YGf zAoq?pPYZL~R2n9qGRy#kDH7(^7aJQ;eXom<`yLB2r-^C{tf-hKtZgeH^ri@< zT3;vw)qYX^cZr`5f6~69nuYXls=3XtpO)1L3_h%*%s7onl4_PvYQBlwp?r8pXlpf- z{M3wqni&|@sWt-4{<{o3|K>ygeu^RQ_o%mmgjXqmmiMF03!fC*4Nv z$=*Kuoq`x>DfXrM=z9)&qg9>Vnkb5`z#jxv>I*cZ8bsFXFokdCYdY_0P7@TTfAI2v z@=bpUU9IE@KP7EYvb;E1`KG&!f%oehDA{m|_-2Qtf(MU^;hPl`e7?!2Lhu}AcN+7= zq*6tFuW;W+PZ0y{5L~0VSL{qs@s`Dyt9W}3eKS~`ti*m-57+nCb0GF~H~~o^l`+e( zNCs1#0u-Bk+iTe6)x4Oe}PiQW0l@7C?{-zHSWutT~&FVgloEsEwI5y@6k zH@B(g9dUNLKK#;_Q-o6IUV`3c-CV7J8|&sW)vSkDfcxf;m(Eg4d9FNOb|X8!WdRDM zB$exrznr%B0n58H)!l|#m?^56A$L`cI9zzC8u8-u#De`mu%zycz43dxzK;B6>#Va6 z2hf6=PBMO1(Z3V%`?$!a#+c!L$@fz|5Oa)qQVb$J<+B$h2I8zl|Au_RY(%|bgXS*Qc!jidBV<9!{7IxgQ7oxF3Gi`qOi zZRat{3?uM6xBfjCzb9)m(6j}03^6X<+9WjXXl+88w!HqGh~HUhKGQy;uhX>qwfSk< zRodhjc*-j6I&s!V?Q)8C#*77)X{Spc(WdRG(_YYZ(7&2CaQ5OJFQ$!P zgpqkVztYC@EvRgbp2eXuOlwdpr!h%)SSm418xl%%o*;AiTJ%j zU$2kfPii`h%jr74>C#9MSh{?=vg!=Z2x--4B4{$>1|}fNrN;$UyL6?WOYxbSy|4(U zT*`6t-)CweUB1fm;?mm0B=hT-Wk9?;BjHkAuBIXKVfZoZ08ZmApWyoyZXs(*x?XUN zdS1aF_U};TF$7z=iX~Aev4#?So-U8>-J$%eY?MSJ_<5GYmSPR$aZ2n4=~g z?5$+uG^*%4K->SReTD86p;VCdM5=!St5Sd-312AN=My|_`xrkJ*qvUL~|ONiN{#fRN2 z=Igk4ihYxioUG}3UZ@Oto_tOWUrP5L@0x9Sts&!bv9=nt8j&W1|FA}4Ze9exoqomA z>JhQ3j>`>}R(hU(S6rdAdQ{g__uaJ&rPE7Rl0QS@$h%O$(y1YYhE5N#A32S(+VON) zvZQ6T9R0X$Ax~rbn6{>Al^y{)V zBYjEIPNO<9qe>$=#I;(rvq7r06lTg@FU$CHzp5dP3>+z{xnI|;YjAvU8c$;4tY=&m zm2jPq(?q!Z0%7X}g{@rqAXJ3%vswRY1HCtg3DuQY7s7CA_@}R;HC|4ds-4nbM;gy~_ZZ zp#bwkN-?2P62aunQv4Wz!a_cymbPsd{2n63L`Ob<(O(TE@)wdxM?APZCJ9RIO#xwj zS*o#;vI(X1KE<87(}WB=)YDzk#hW5(XwVC;5%#s?D)fcAQw*+ z#H+^XFH%=mQ~@9ioE!Oh;|B}y9mRrab*8*fI!9WB#~24MT|)=zfX@o>rlV&czW^%; z)jh^i5V~e~j0BkInw=oH?J+7-XlKhi$vhsR@ttI61YgiA?=fO%N*n`%gCwT!z{`3s z+{rO!w)HxgQfIo~+x!9Vi@Flp^rH0mjO8Yjf+uD^hH&Lh3Q?VUQ@yBx0Kj=%m>&`n z`_WL2$R@U%%7}0Csv{wpeZiIRa|!$*wPl)GHZ9g5>W`9yiYkCVLaQs=@wN{%t#=fy z#sZZvn;F`b(5aZF)lt)0s%Sm^fY5plw}ny~eAK zgzH?ybS2E7zewxXA=GhP5@ed!oe)v);Fi$&nK1FTT$;{ZSQh$a@v0-?SNIV9%>PXi zyj0@talNeXN$@3514g!|QhP{^_whR=@ohW|nc0}Xk~DVoz<$m6ItV$f8N!L1BTc{S z856^P4Tg1b4PVDa&i``y)tqDS)vwJ|g-}`@zBf93XVs)$Pwz;MKazF{8GIPH;Psai zoMH2`r>{X+@_~ZF+xLmM{hU-E_);&K=ORt4*hM}dLmt34SJo$LYGA`=&=2t0lh!GZP zojt~Diu|`i1LTML$PYsFZ5fD<+)5}ut1Ujeaj^+R&|iaE9%(wmGrm>WZ#5aI@Um>u z!kA6u_utXp*unZMD2j<+hlCi7w&MA|$hza&SAK6d@q3a^os&8ybxL{)aXj@pjfWi$ zvp9c}2V~AaSXyx6gMY?xS1sJ(+=*eWCt2J@1V2|3SAKCShfQFJ(wqNaNLN#&f7n~G zTU#kc6kZV720+#-BYba*s6D#aUM4qZSCp9`kg5t2ciIF-GAfOJ#r8ufNahA2;*A{wuG~!*$u00v~iIEXVNZ zF`P=){+zy8GT8e7b^u|WwwAo%vVX=k1`psf6#Pzl#)6L|e4NlG>>|K=j8_$47MDFN zz@h{!1VGe<(@4Q(ydZna*o$+lCjFrjfR?czAVStOlUn?|@M~h5^g@uu2ol1uX1S+8_F;w+6*M<#=lpZb76woJHd-F5_jY z0NJa9`e-`IWqfPhYuwMDax~FnDQEmCe>p4hdKq577;wD`ujl6Vp#gf;n8`5K`!b3W4GFbYpp4Ogk}V_c4ont3Mn5R*v&7?soDRs) zT{i50z<`Q=`2hO4+)atqO3^B zKVOoVd%LGdz)kx+_};lS%4eGs*QETl=j@9&GSjb8^*cJUa=V`*`X@k7srG2#Nd-nb zVB(``bLw?}Yvp!#CCX&sXv6?UY119^Pmd92c^3t74tIA#b_ykq^cJ*7qAU}7j5&R& zoF!cz_dpUTu9RzmVhiTQZXu#v8!Gpx6kr%(ZI}8%O)4$dPqO8}VH8eV8HTm@hMg_- zZR-bv{ckK`%YkiY5GO!3du017oyVO7kS<95&f@oqT1#Gq5Wbdt|`?fQngo*FnyNE>;8b~nLrN>iDAH`*JfkH z_4UNO?zKdjB^-@pz$mW`#1abT6_8GXIWJZFh>*QQiHCYk-rn>WZ}jx{TR!(@5-2aM zY;j@y_K@W_+u5$V3rnUu%9iT%PxSD=QJXE*>HlWJ@aD!JC4I2d+tOht-;J?sIg+Ar z<05*l@5TwX97&jl*dGQ}GY+ZRXQq7aLzKNAcB~5xnjwH^(A1SUlPyv(_~dgRB}#3e za2^8~6*PrV5_ycvPixEOqh*g1GH+PoC%P!&Cjva3&wYX@$G;ci9|J}a|7bXgI|7KG zBINsk43+#ROx-B?xFF)Ei859ZKL8j-yuA>w89+RXkf~vb50&hB*yLdEi_v`U?}+lC zBHmoGCq87i|Axgyk8!w%zgf-_@<+Tw7b^KWIGB=e6*u{8ex4{>fC8J(0*sP;kq{ph zK>Q*hUkyuquXbpkAmTp|rI#Z9p4XxALfi--eua>6p~UZz1x9rD&jJzdTSUM8Ew!+9 zv^t94=$L4A6nhD{-gF?7`Yasb{+;Mw06jDdJ9zDtyJ;b>eC)i~<( zewI#Y2XI`bqjCCc#kdV|F&rX$tO)EA1?1# z<9dh}ql~PMB-O`_DFJGX5;c+%aie4asr-smGHw*^T6l| E=-77$shDdq~VAjlhjR6c7CR5x=CIbR>;Kvy?KT6l1Ni zZ`(;+%Oj?oIt9K&t0!W^N3$(kj;S-{p8ZXj(EJ-&%okYs-OcIk8fU`w;ZLA7`|#cK z{^6V7-GV50PD>x20~pnZzef3vbGW+bSS$dZ?o>h^0%T}{*dT#^*jyS!yfsl4E8_D2 zqliB*#M@cK3zB$SLXHeed|3x2d14Up_C$F?5uXScMZB~S|FyH0oNq9@I});ZSmM9H zs5HyPbAe`giYVv55wjeYF3P-_`3%jn&?1ianR2+h5b_H^hMJ|dmi(n4;@yanu83Fn zO5R(DH?)Z3b+{bv9)#=`mUtfoJ|(XfM7$?aswm}KWc%x+{s($RJWDzey;{6G^EG+RhTJqsR#0L`PSw*~t zSMn4gUcn;H&nn!53E4O-@xI#T#e#?rAxaTN{0XnkucLCt`FEYPS(roJ!w7l#WH_^I z=%{SI0RyUU49M?(jwqi31!kEC7-jQUg!nTSaehVQ9zjS)SmJ}*D&k#&h>s%5Q;K*K zz$oH%g?J&0INnXq;Z7rD&9KDxBU3S2{=_ipFZo!a{DEb0NWKa%iuei4?>xpw9kp5T zML-VsI6@uH6-0ajQI;s;UjjxEA1B1yTf|F{_(VdE3QPRFHcL_v@kvB^ zQW4MenuYUJd^gZROJ0)1rx4NzOZ+n(ikC1#`kQ4MQ7(KfW|`{^#jU8=v7T%ZFGb?% zgxmEsT=Bp)<<8f+#;76V-MBM$OC)VBNrDtb}w@lSNUr_XxQQkU<4sn3^mX;5~+? zt$$5c-o2g#W(X_WenhTR0DfytU*MXm%o5u97XXj2B{MVoPDp5akj;E5ly`3=-53!p zcoC|d^cLMrHb7>mJfq~0iZ%7Lo+1`?+)WFB(=O;hha91{LW3G0B$zO^7AFduT~ z=m(V7fdZIWfKh#G1QyIaMvK-u${uEv9z9ilthP*_UY*1rCgilR#FKO= zwhJO&ktl5x@hER7))3-0i+BwZuT02FVTt$G4*eBlqrc=;iE?YdNS^3*=pjseux~^Q zZI+rOUY(G802vzR&nGLJFAO4HlPL2Q@eY7dHXkX(TUx|pNW2yyhlVBoC9){Hf5RZ+ zwTV(+5q}FXig%*60&e8@z8Nw7K>AW?8|$#-3dfLypJZbEp4iY7{5{5 zforNH@ial&?2Bj9J`2}&HzN96pofm1ZGg#At`~-Ge~wLw^0aU?Y5+!+at*MG;4vPs zRI5$ZniDcMlz5o&GZ)}J#;|1n@w1M*Jqg^}E6Qzyi-O0`HMpiql49sIzQH07TdE{U zg7M8^$gVyW>bSd+?wg<+8ZBLQv^;}R+h?dc?x%?|NJKH>ywTDa%N-sg3Svu1Qiodi zB4k2X;=?rYLP5m)5T$@3p6n%l8B0YTW1IDyU5NK1)a7^%_7|3(yB^0>`*mEq@I zfBIH}F)13nb6Uf`korZ{166Uu3?Owzkzz6Od;rEXs!*tp8#h_WczK*-%ONXot^nqf z6>}CN5;tCqw_tH#aOLgOM1NB6vE@i&F>=8wUqsxmmAJieV>{B4kNKx;Ig+^Yb|lIF z#+Ph4WaaI5WnF;Wz%Rd*x0@=4CCIInw=)vS*2-Ix0P!9b@vN1%ZBWmgj`Zq_+Pdy_ z^!CTQ!gcRtc#qwC3I=0efYfz=Oq5AL!DvwtFsgfZ!)()I)N85(J(hv~DIq(CB|cgc zuMk9h15qAQ#M^j@|BV^G$2iqQ6R$_&Ul8*5ufj>57coJ}cVWErmwXdZb^-;GUx2-p zVe=!20c&xruKO#ZtOW|p;*{jV zHA9CG?`ILOPvW}?IXx`#_S!7%gNW}XN?S#|me(vbg?L_zcmopOPsqw)i7(ZX|AtY} z-=PPI^2-j9e7slk!zll8o_Ql}mWCvLn2>t`89Iy|kxq8lTogq7C{Y$D;%fk-Y(7ee zr&`40N&Gk=hlM3x17XHcj1MAyf+!6X@qFG;G=%t%Nm}y9N&FNcBf}EUt2@#67(xBb za+)aLeyQTTu_gIN%o*{1kwrX##Ip$b2_QqwvNv8yJ~fE=cSM=2h`$FIWtQ$jJkBEi z1c{#|WT&viKhrj^7)1O$Q65&r=X!1a52lZJuQpMeS(*s(au)F<62C^s zC&Ci{8ws1yVhEwhApe~Wly690ve>0ycQZ=i^G2qOL)QQ9fus{o@Uj}hYeEaFW_{C7fD z2_+t;7R(QLkJ0-H|5~uQJ6C@Yxa_7LwtDbVa4i^(YpQ%HfjlHbvMd}#u%*^g4qC&f z+;GeADLdi+THhbzGFz&ADFdB+r0i@tlA!W3h|Z}@fIXrpO8bt62A*Xng0b5Z%CB-iug${@!~@KX1tcXC5b;y z$iiWX$7spF+Zkw7 z;^~s<7%km|cs+}FD-v%)$c|x&@7E5k5JbEgQ65snS9u-!H)?s*e+{)+T9bG(A%D*Z zC;6l3ZM6BW9f4+PL6n_9L7W!@j55nIAwIz(-iE|e3HfFy@i4Qf+&`9xo(sEstwbRchYXb{B5Bi)MlQBwE@fYc3}9~F=C4~j zcV99zH`5%!i|7lbXC5}cz_{wm6z$vth_V4FFvn==nXLQfVd{eSOrej=SliJYg9zyi zOT2*C`mot8i1;%^>7s};U#i4kPly)|AU>3kwZam&$I_99&A&19`AhyRQU2T{l4sYo zh@Zm54*TZS_m_M)A&&ww$Sk3w3M{^WGedQ3ad-Tbvx3`q!8N=DUkDi(XU;W7Q_c!5 z9S0}8hd`At6bhk*gK;Vm80Yr@+1w;!_#K{DTsX<~dCMCUOR3Z3G-Y7}=DQy7K+s$NUGqj_#L<_wz>HwfzVm1`m2!xTaQjcpRjej_m3) zWJmXGqJIMP(C)unqUMk}H6YMBx?ds6WZ`JMC{e@i-yPFXy#EX7M5m6_X&xavg%S_# zM55Z-Ge*oEhL+XT|aHJUf$JlP}L*!Ihae6nFCwB3muVXMm zN`qz*WAd4uzlYp7HR=(VLZ85jS17x=j}Y<3hA^JC?Zg~H+s1(i6^SFb(&DvE+#jg& zMB?7yWFAMniEY}W1&Om*1GIz z6z^aAEW`o`$K+~beQwHYn2TA{pm3E^V8QFi#e z*WLXK8MP8dupIm-*`U;_fx6`8G&DS1^Evq9VDrVS@#D_*J#pAcvG3Q zyZaAPJNpT#1-Qp!ybUN{hV1FiJphm!00~EW7eBq+#mRdtc!O0BAFDn{9KxzL`nAOh=6eWDVYMDT!W?R`dIv3- zFE@c*Mn&eJ$zbJgz7k|)7e*34lcln-`fe|GDc-+<@AvLAetxgUF8P%<=hR1h<}6D} zD})lWhVPJGs5qW!Q(5yZ_(N3e#DU6d&6s9rii(};L5-P+Xt8ED0=tYp9ITgY zV{bHZN=frfo2j&y`(fT+hWij?Y%PvLU*l|T6n|(BWEKuH5|Z9Y0#8~RN)g49EH?n#F4N5 z9p>&u#CL%h9KZ;V3C!=xI;=}Y#?*oV z+UN;FahdYl6VXh?hw={4&!GiX`5Y0dwq;q(`I4W1N4i&&b8m1)tUU^e zkbKNT9D_srJJS6DVe45^hWBryK>r@E?C0OL#Q$~GJ^hQoU;Hpl1z9dspw`&7Lv=~S zzoKM!q3e7^LLUkt+dL#FZJu4oc@h!N#whdXi0FxCKtv3Hkme!;s+g%WS};?6BDsvI zAY!h;%*4+ERz!?;ZzShBigQUH=f^R2iDN#bvwV(Of~Gj;&+4FB+2VKuEpVJfV3*+m zW3!;}& zy@&KlfL>@?wH1=thCTC3scUXm3aV=kqQc26XG>Mz$W8KQ+1m|kXpQxfXdeAorGFwig%)zA!Z`5B_1MGhLH7K zmobl?TY}k>Um-He{T(?~1E*HbHawgDPk1M-VQPHBt%vY~Cp3+OZQ$d+nEmK8>3iX) zY{2o{!#Q(o9R&s4XG!M5yHus=h-6OV52iZm<1FzqSO4;)IA$yZ5G-xZzDzd-t_+}) ztgWcsVRvFdlcPjG$f0JIL*182do(>U+Dn?%Ut~2+vC09@ zs4Bb`P*WN-XKD56evm_*;)F~5Iy@svllX@uo&<@I653Y6C;S8WDRwFyD11Rn_)ie? zW+hAbchQ2KZlE57@FzJbY7ioP&Vk_k)jMLR#?hAW)LRRGd!G{i5H!wbh5X_IILOADVp~A$CB5qKGavBv- zDIsKsAi-mO34tydYC9WEv1=n2V1lDDg0kZiPrYP20)K)}7 z4tFK8sxGXI9O9Y-<|0%PIzdM&s49fY6HXl{@nA(7Vz(Fqs(b+Le1@n_%zfyXK?Z~w z#+QNr#SHGUdfxV20B%j<&H*mWkj9Rv%+LovB|-fCkVwK;=igl&1`VJ$jk5#2ZXbP(v7~IWL7OS&pfz^5f zyNsetC^dzZnvQK1R*#X@#<#u0;j3ktOmzkmhz5jM00`(ktQ_xhRa6axJ=k_M#cA~e zqRk&=sMQfHs7XZa4%8rXOJyIDbr(Wj6~fH8KS%jHt|=)M6-q(#4M@d$EZJorUI_X+ zZQn!%je@%|eX>SDC%TCm1(%z<}*= z(p5pw1V6Bm)KvXec8d}iYATXYz z0NHGZ*_W=sBex2x;bisQ60$N1mY^0`>pOt&e_I*;x>yA*0gQaOMr}2QK zMucUz0OZj`o**o2y;NhB?S?xnY7FH>ou4=;}@*1KkhC9kEoX29dLuKKz1a=uNF5i@rJby`84M%1t0 zgg!w7sa4oxAGyF9{^8ZD8EX|*WV!Jpz^@>0?dyTd0;2| zqiq8ME?@!lT@>S1iX4pmsZ!*mtYFz+Cx=eQw+ic>WZe#|bS!8mPT@lV%}jN6p>v3It}F=S4aD8Ox}5S*Yq&VoxkJXd zQDEb9@i7v86+}ZirtKM;Tp6<5W7?1hG4b#-i}##u|YT7DJXt3x-@oB$siT z&xO)g`gFtct}^5W`tVyy5jsc#*)42ng($ zKL8?uJ(tGmfDR$XnWl`BB_*EG1IXqe)Rx|{@e+-4oveO&U5qj^Qjhe|X6*z1+T0}6 zK|lp-gXFye6GtszGP^@%T#IBE@eXq_InWdVBcZwZ2_jVl%!wAfcR}^Mg6synP+(dF2tUJsOU}<#* zZ@>uayJUUpHQL6OiOGl7@)inV(Q-V;XRnr(hM*~0E(a6y00K?4d`+=TC9uob0A%wV z<{94nBCP%*t6^ZJJ9)DrtVVSw7l?ld(LxCmU5s~6cq7zWT#Mj!YfiCPDu#0q5Sc_s zKkb^El#G z6n_;hxHn#P&WS)augG*>7fd2k0m?M`Rk3kbAFFj3v&FrcI@EPyU593Xd*jHmx5cuG zVmVVq)H5JrrjccEVinef$okGaug#AYW@43(TC~9m6XGNwV23sEi0o8kEoka;<#k?n zG{Xbkp3!C%ET>w`{0v`$bmovwP!+}Hh@f{ZZ5=qzQXPI7>I5bO z!qBiUI)@m%D_Su4ECOTw3CQNy<%~3W;YjOLnzG~)os4fHsna2Iggh(okG8Ue`gSfm ze1Lp%(jWHgwFjH3JP|$wf)$jo6&7hQ24TURPs1*8uj0Wtg+tlT{0n1jV1!pEiNV4% z@YMli$RIJ0gx_U$(~rJyV?S#+&zF5`kyI3=2{Jewxk62OAKyR~Y&VdD0_wT1F~PLz zxkV4C-_ho}qkhs#=~AC8HoxMV@}i_R^ASusoWL|B%mToG?L^X5Ztcq8W}008Ag=k` zx*Sb$Ycz%h(}_+YZY{>K)n%JbV3$#rLH#x+C0@5)WSVSDRyDw?m9sUcynn+(T>Xvv zwV>39*V1ywEVlhx1w4m811a=wMm}n-+I)hF$=%G2>Pmy&2u+|}bsQ~>i4=*CO z3Pcw|m@e_w=dhY8yLZCgs(g9}*ZAlHa!tlhb#aWk7@gu6UKNuMr_rP!-}QVB78SLH zaz9d@1Ii&Lvkf456&9s2Qi;}m0;awR?X9UV&j&Em5Y?h}meRVOn)-gnF=ysdhK0PG z5V;j&0oDx2xi~m$t#9V1%XLo|h~b2|HCwcI6tQD_ z*Z{GSfIuM9M5U<|+k}WCFim-}hn zC|+zBSnp8`weFvX;i$Eqz$aWJf(9W6!O{8x2?X~E0>7+ZC4w1(AY}~tF!C&ZR9faf zoEt!hJcx?89UFX>aT6pIH`)P#SWy#_w}`V%%&sK~YmL>kE-Zw9(Z#Qbke)6&e2byz z;<;qVy8}Eybn!4oaGsR}jv4(h+0H>};v z2un$5p%xpT_Th%@s^J?^LvNbV^~}YT8EwQzA$`9QAbl5xLi&$b&%O)hETnJ42&6A3 zaLjlJlkFMoD_HW(GW;=G8%fJPCt*!J(tm2;Gb4fck`M=?Li#r@>7NVfw4mEbdOj4Q zc;qu(8?vf6b>V#7Y3z%qa*cylJq4oRw2E$BE7egx{1klC5jrCbVTN)WmP2X zDiEeU;5?A-I1q6=oOd606D9TSAVNq#4Kc)L zFikNOsox2ow~xZ`g!Jn%g4BOUss*V(jmdVZpLBHjl9v5V!k(Jxl0Gg3(!DGUSdf$o zWYQ==-UUcddf+6iDNUds@JY3$ZXpX(>pC}z@Ci34{c}7P9z%96EG%a7gc1c>Pl zg)R+YcU1JBE7pT^e)&A-hx^~V+S!3mJOYRaF;bS)5klOk9hba8mQ;C?JlamVlr0yu z%McuNs9-L|-*71CBoD*7BEdq~XwwKBx#ttAAan^I=$a%g>&B%UVd=#15jQFT2<8=Q zcy@$zg1}$R5Z0E{ER?Ctf!m6lzfAGVx$SBUMb0f~Dw|-CVk*hXR9+!)%(xPh?e9?* zxuuVw>P1v{3M%87IJaFsii;cV9qI+DH=+6hsz#>>!cF%mOhGVEeu%8evxK%cVki_I zg^28q4uwBs1WV{m;Fz(I#@w?8g?Yrip;Uyih-R;ZaSmOcr+w~ht5E40zRH?q|CyhHUYgzdgWJrJmu)`e}wjdSbzLV!Tz6XJYDTr%v* z^y)(Pf5e*()T8(HN;9Lw((Pg-2@W!!#s_hoy(P5>n5I=DT~pSnp8B;UN7f2HdKw2z zVsb*;)m-yYteH@7LS}{p?UZq^(DFhZ>m+31{dij+D{YD$N_AD+t*VvuAw<)Wq?7jw z`=QYl; zLJwk1Z6l3g`eKg5Xg6M9>W8761p6BC%$^Us7Khn@5zMiZimjUv1nqZGuRDj;+yEsg zM-ydNL1`R>r^!Pa{0Pdgbu=>qbsM3Y0xHq%L8#68Mj3NHVxbWFJF_~E(C;x6zxjlo z{U_{92wki^do_V$Mk*%TCkml@>lM^@5cOmCiA?VGQ1x)ipB$e|klmk8nY4#aUirID zl0C~o^>2(Iljce$A(lV$rC)$}#V3A(>Q18iCs1iWX%Lq%<5SSxggAl3;Oi-9x`X{~ zNi2VL9sel@a>(a8VcALbDF-vq{c`50Z5 znf(X*qQuNcwC;7xoPl8=W*SIU?3plIF}H>o!3IVu8@L6F*iW&#_gqoMOhNr1QKu`^ z^Nukptbrmvg=^(?%i#%|D;8i`oUl3DZzMAHAx`~%DyddVtSPOF5jxoX{lwX4A=tPv z!1S>{nLGY`wuwprcH(n?9=J?vZJboU3GuI&WJ>6XzG?t{^a6y8#vaE)@hNtkT2 zx!`W6g8OmeK3!Na<{y^rR4Dukk`P@A)RTldI;D0BH(^iG6t05X3Wf4Jac)>>I|I3w z`0A;oa2HHWC=4qKM=>*t8Bt8Oe@CGar0^-?o(9~|$~Vx8JR*k-FA7jNk5Jbfhr;nJ zcVa2io)G_d1u6;nM=BZ6{_#1s7PWiqUFM4kB8BX+?{Ty;KHt)cz6F&vO?5;>NRvXIbs2@RnFtfvM4kt6tl zKGQ&u?B$ro>qjB@n_=Z5_<0z?LC#X9F^z(sB%KT$Bn8!5MAcBS+vOldr=IGU|E0+n zsCNjpdva~8hn6stQ?@$>w2EbX%j8R21_=BdL$Qo{BybfBQ3(9wFClO-fn!ETOt!a6 zW*FhY6+ZpKguybdJUZ5;v!DgqY~ zIA*MZ1>4N8mUE%s z?x{&@+;|&+F4h=rwUWTA2#kI>w@v6F6qf#bo<~nTZ7MAnM+Vz!wo+90KbE2>hB* zr`1m29PCf<$Kh>$ax@j>qWU< z7>b-frJOH?BZ-_pR&qW|8Nx37u?I-EL5E>MwV$YVjw5@am5f&k)pf`^#rJlzIP-k( zGYkX1cQt+QQ`oSe?5lk5bt(9aQ?ZD>i`9Oj?+NN(i24SFde3ikLFR6$SVHG+kIcie z$lY%Hg96$GGEf4@)ZaMuY?)eX?xrJU37J2^#TXEfL&Bmm9>BOvL{7pt$_X| ztWN%2t5%3P!nK}~wGyI0=x&rwTA~N&B=UVB+NCGaY^G8EXtv~cNc0}qv`F+7jNmM- z#F&lO=q$6@0H{@>M@dOjQeqinAxC`E2_(mjPa$2&2Zi3h3H4JUp=uQ#EWu*Y5lhKX zzVlI{?>t4<)jQWngd62M;}&~#`E-?Z3((yQbh=`{6kv%?;83C}_I%)jw6T$80ug@y zELuGfL&2dkU7vF}%p0R3&h@W-#wp&E0};k(IlXeW1lW#zxq%K7YR2&;H6a78eb ziv7d`(8bTNGttGd{i2I=2^=$)(7NlQ6H%jL7nG?)IYUqyzpDrf1IO>5fk@GXKs6=Q zNI?A;i6DB_`x!#UlYh&20+tvz{`$qgNOLZ7isEj~5kSUL?wU;zhVBM*Am`X4U19YV z-j|SdDb0QOt}g-!T?Ut|xQhbY%&7MOAQI#aVwz)lsU|Hf%joB}Bd-Y%*pjQ=gVhqb zj2qnm=mx)q)YTaT&Id5)uij6y;i3Db5MkV?=PWCbZ3%gXf;{}Q19|Bmgxq#OOGqHk zB;?^c*;T8+4WIWYLlvO22=qCCU=Z(ft5rsFAbcJhPm2nV31-Y zNi^PAh*;Q5Pb-7><((3%^?2%)Td%Bx?#GEgXm@H z_TZV6jn2Gf>Xn?j98+ru9@{|8V+viM!3Yy6w199-VK5f<#6Os8jUyQeg#r|pfr(0S zw^qZWkUX>s%q`&Di!c|k6<|=ozJ%ZuHxBIcW4V@)sl;N14#v5vnPzrN>5CvOl5dJa z#wYoD7>eYVQ}Q9Wk|_CICHe2UK+I^&^s*&tClL+Rcz( zxY8G>F@%~*s06k#>k+t$yy&ZvET0u%#x zx(~E>fa?ffLotFyr4Tq~45mfppzGkCu2@38CKB_y+k~&awnHKMUJ$&e&PjxN8BjIp zo5H!lN$>L!oak5ZE!8uh91uMxgIh0;4Wv#`Y}A8kfHJNM9*2cM$qQ z%{)}eC^$qEj|Ejc(^2t$?q#PtsCHunRJRg1W>m6%zW}IQ6$`5SiE8;6UJfn5`kJdR zuqz9yTuk%0YTE@v;c6C9ErAsZS5p+KlL;I%9>-+662*!eG6YqWsICGk?Z@X;5keo? z5D1G9T@*1VRzvV|Vnsdl_-il5@=ep5)9u-^C+`AbFjblQ5T_m)UDF6_`HEO*8R=B& zdjUaQ7-in&G1~np4298u?+2snVWq-o3?s;N3V~zB&6sTOLDAzLbr4z}BQ3X+7W@vQ zhbj-v06|s8y2^`C%OMH3mjHH;9${u^`kKq1B7`^gi zj3DUloD?(W(V`}@ecK^#s27ty;Hu4J)r8Ypq5H&8QhNRig0n&wW4{Tcg_S54oP>T3 zg1<@&UwqX^_d>>=mBhf-qI^MWgMB?9BtzU_kHW{q^p5F#Fi8g|%c^wJI9Mta_nR7V zqiukjO5)-J;{?Ns8zI2C+B>r@==y@NEddKtiXU>#>(gK1zcjB&*lB#`HHJBwzvepQ zJD67kc#4>pff3B>GERya_hS*e6+01$HP=~0y_2Zt-AvTRNwQs_=E9-s0vL;^MhM(Z zs0jj9Yt03v?EenmFXOuhW&=IF&rPON0!vkMsSdJKsF}y>e0Y`cx}UoATxl1E0bYNE z^6ge|SmAXWbCy`>eNKuQL$HW_E*lStyq-f|e<$j$GnbQGwVckcS9)st~0_ zi{PbRONV+Xv>Q@Yd&CxeLL5uCZ~euE}7;r$wvJ673) z$SYli4e;%_aW@wAIBmuS9>M}9UbrF?d@&3b-hC&fg;h!*HnDIeG@SnktYdJUzOqi} zJXCX9Lf;^d5DR|<-1;nh28Oh7VwBCIh?3%&U6ItyN>U>^DP}yu)Fi_0fhPmCS#+Sp zS`+og>xI{T-#EO+jR*Gl8BHhDs{&P%QK)q?nl_r~I*wbGX|?Jd?kx-hL}%{?VZ|_G zA^Lobpk7O<_d^u*_G2vY6Nx^TM4v-)P7!iKbv)GLC@&VSFS3~R-11QjMNWh0mZ=WP z-pVZ}5IAOZqnt8;lHCnT*0n4_`A?!;a2-twUC}jmD<&TxE=|m2tFkJAJeQDD09l(+ zWR}q>9Ik?|kTa(2fDG7lQ?}M{w_gS4bJ?@FY@*AC{zkyo(yv6RASUww&BzOilQ0Yf z#p}KXyCHarNPi$kkp3V}iWxJoh}{ykk;9<-&5@3j{>7x^>1)YgsMtfj3)`GXe<5SE zC;j;tia(F|9?SjI7gU!J)%gllnujWeZAZ9lPUU-C zhS)pwJI3$a=Gr(Ye^A@pPGw^zE0IjLA`)#(P-heMl96sae(-A&r|WEi=s}1_00B9S z-bu^&lC2v#lr)569MLr`9VS_C|Dg9&T9+~yS*H)z$;Ud0@lp<81iqmFOij2+s|fli za$=D!i^TUaF7VgOMB+PDT-b`ckoeX3V|PY%Kvauho`Pz!LUpRzWM^Qqy+*2eeS$_%^(U%9K&5xQj$aY0 z-lhcNNE}g zz~8%N=U|&;0DgNKNvK|gO6VNuY&^U}ugfw|*1euHn#sCOj_iGJibvwC%1HFKbZkM| z#9>j9Xi+}nrBNLE-rLuwG*QbnQ2-@gpAYjS!AL!598}H(RF!`acYeP$v=XN5W;37E}~k$q!?H5hbr6DLPg`$?sw)N}hzR(Eb6ICrZ8zBPjV%q1(8M zo6`}g%XRVjPlm<&iE0K=>Gv`eKwa`)hRe6%17A_J9#^o;vLE?Hmb^6B%ZKD5YCwG?}g=!^C8J1!@;JHV!4K za-zB%sPryy_Lnp`9m)k_1tB^JF;2aMZ-DbP+^lzgfi%^Q@FPCSH^8TGQx7ar$tCs{ z;BsPgQ|Xu!-Mm*QLd{ogW_-dK7?qAq!1A7+H*m$rWyRnNYoOrEFp=3lelO^A6acW1 zivx2vaqdvgwL(1@QT5ur3+&(E5?!t95Y&CvONp6jhh*c zAY)ZTou(Ljbdy73-1zJZKY`VR`gL%v1XiH3(*zFsN)vcPkibC>ft^1C5nEt_Lg1Mg zLGl+W0@ElSCFv=~kYSU&T;l(GBvp$2h3kV+2&Q z2pltxQ5Msr^4CfhRDTlHNeb1kKe$}|h)60~@_NmcuEdsM7zh;Ww_(}Cut(vp3?ra? zLUH#T7O_)^QWraJEg+~56ZM0GT<;zInSx}B>vmiP@-IT(3`oeM`{&$E@NyL0V{o$O zw!AK#*Q?X*_t^1ItgvJ$c6h7)!KG@Lt18{th4Z&9LSHdGQ(m?k*}q6-CiF%HXsJxZ zFi<9e5l$LPRsjsUPsEM-`w5ZNp9RlnsJd=xCnC&6Yr=ro1u+>BRa;?9Hm_{pLeHvc+s9k?BG-ORk_)@dUZTzJ*|L zSbDZRiK?`3!li`l9_3ZdtaLWwvpU`~P;z~|$+Ufdr7Ys=3tR~-#f=jI=gL%wo6X?b zixXO50@ysTj)YZUtGZ+@Q`3#mq)1C3dlT|Nf2O9(M8!Ham76ASZpKZ>ZYgRRZL4k{ zsRPZ=wbd@I9a|lQ4c@MR;fbyG#t62Wq-<6CNME6vck60F)rY7?DOCMDR2BpxZn0b^ zbE>Xx`woWU7Dtdl*uxxDKVbw^kEkTBA12#(3MzfZLQqAB>e%H}6W-0g-o67_ftyhY zL_b38AViJgxQ2f~u7lx>Dg}_kV0Wzd3;0T|HAmJ8+BRf*Bda&%{}(yQ%^K`zo=iKu zkD)Mn-a0T-2(uQMo`DeKpD6 zL}a>?ZWs$CE90r+rr#OmRnSg{6LVR<$n+(YdRnH>qi_>c+gZVRGOff=WcmP6ErNXu zs>uq~8w8FSH{p-H28D8-2d+C)3Oju4rOm`0yc_`d#6CC2D+&fD`a_XT7)e(@O1gJzqH9CV{If|rG{TSBvl)-1$Rd2{rH9~c0FJ>a-Hk$z1 z;ysw3CWPGUS$pb`dluYCh1~A56UiM*9C^Uug;=~^aI^hej9jA$@Tq+W9~0sucVE0Z zTJ1;)ua4ebDJ-GwuoF3pv;r1Gz#d!Ui1N$6lu!a&apPf8#V#lsS;R|>xYG!|0MM*& z){rQ^{;)aR6yN)B))h$Zz*SQeM6I(_?$<*mQ0wlnUPE;m<;NI?F+g3*U1Mtn(z- z=_l)iIwQ%`j6MkG6GoF+NO_DNMlBIwG?~#X3r-@89#MgFGb;}KE*BQDFJ}uOk0@f-hw_pU>PE*~nrI>7gh5E&f z)q?6pq8bHM+Sz-oB7_d00`W2-E)!y$ECVmuamxG?AWc=~C()+ZPJawNSa)BOB^Gjt zdR!uy8qrTKa6~{qxeTvZU$0)Vey1o{Rrxr>_OI1`9lyf`-!|zZ!I%O4j>JT&)iPfC zgbs!>e^6lZB2F&CWB}I#y9#*s8ahJz0OZGn>tVmrLni{`z51AJ4@6Pt>fsHld^J(+>P=L}Vj*gs-A`pJ%G(8M4WZr# zR3hJ)wGpo5Y+T^^S}fu@#iyJ&T_y&?E*L97Iinf77bFT}lWBDBZqns8427{5R)P4N z;S*wDk75J^yPUu=BO8`P*9s2D3PcSywVKda8!M>vgB3yb9Z?WjzVKRR1=*He*z@uQ}8Vqih}zS)g%X14~42Pfzjt?hCc_WTqhP(2Z`zw zpwd$QqfCh?&EItq$U}turKb?J8oH3Ki{6ZmYR_d*=2YhBP-4D^KO8mVwE8;29$8J28T+|HVl-=Rs4P zjq-;UpxIM>YGJQFX>2O&8Fo3@TVqd?{=c7-288;l2Zf*;PC>eL3t-{002+{tXg(0Y{M{&m$A0XuODkhc};i-!H({ z5jXyXmc2-u#)VHNO*PaLT8R*Zr1Xc|AWA%M_&6acUC%(JlhS`-(@;t2f?^6t%S|$z z(~08U9Eufh6j*291PFBq)gH}{iFu=(5l?(1H4)g!iIs8{&`KV9Zh(9?C zqTZa%1oSy5-#ua{H#_s@V%&rXBg>q<{x0nLabpaiMHK>h0U>88$UZJ)DzbvO(IWtP zAtA2=q;}kkKjQMcl&Q&DT?vs52(+8z-B}aT;a2}(m7(O&4JoXIt|XQd?%vt`7bht= z1Pbi-J+&P6VgxyCR!PB8c$IxAsxnNP@T0IB8B`9m_SPt%Cs$%6d|mdORx z>wzE>N~1A3SJD`Ocq7ud2r0cI4Om5c48jlTc|9Q`fYj1B^8+rgb7NWS211+zh=5fzpi-3_PDBwPa_Ga{=DF=1YXE&ou+qv6IQN639_UAP>PI9f80)N-z|G zGy~E0&oD3%NC+bc`m5xMyuZ{CTU5JDhlDxY zjW>MT$QMY-v?S_o)qZj{3k1(J`d}!Mc=jD|`yGr+B=HbNkiv{8L+=L{Kfj?y$XCQRMjZ+=|1ac!GyDP}&7depS0{Pn# zEeV0#M95}<)RN$joKq5Gl_Uh_Gs5ie3cLZMSc}9`i{fOY+!8WYG28G$2J1Ny#S9w7 zHrSPjVuCV?CkPxfwxhXY?~~G9?;$5p6nltuBCy5{6C}GvAveF{&7mX-zXJfgrnK^ni% z$51C@vi*gW``Ru}qBI)c2CUZtYuxArs$IK~o2k5+OOmY6c30a;2pe(Z2=pmD3S?74 zwo;J0T*!F>xiJ9QjF1PqxYAhrwvxt7R~oWlbAqh_SRh`o4$;DB>hz*Ekw4EgmSZTU zF?}HzeisHP!nhkF2;&7Mj4zO|*%c_%UDHURFfxdAAdsT}OLKKhLvEhQn-}6Hgs~3M zN5zZZpn81o9V!)J2xL1#rYOkDHyy|av6;n<6#>Yz3HfbjR~R3?rGzop6^1N$4#7SI zn9nru9wge4Lt5|xANbKVv7RZYUd8>yw7l>Wm3q*H9n1Dcj%irr( z4Uy*f#IO0`1t{FF2$CHHeyA4SO_my!lTNs>c}Kt>6f?oo2&KZ+6{@U$b44-oR;c|ytSq*o|; zPAG>=tk7zda8#1^@LkAqB-}m2B;DHv=VB-x{_-2};?H1g;^9wV1P{N9z&O8;$@UK{ z;wfR~M$O3AlceD;&=5CrLxhZ z5-Ri>`~mQYO)NO0}}(89VvzC+0N3i3SHJQfP%ZivBye3y`Q0I7wv<8_jjn~|*~ zB&#hV%-0?L5-Lbj-}n;cpvcB^5K7k}*B~z|IqfA(1G!_|Fnb-MPTUyk5FwDO2{{>% znux(dgexCKia=Hn@=75kw2@F^qpR>q9Rp(oN%m9Hf|P9KtbZsBo5vvSJh#RrMB3~2g4S|Yay6erI-aV-}s8d++Pqle*YJO5nT)9 zFN8Dz88^NY3Fl_?CkNsS0`V&$e(OLKMjf?5#f>)ui~LTIjRF$M=wAzSPrOQcYbxTHvMV6t zMnlbh-8?4=74_zmd)e~n3lZ+LZSqq z?jH=Skir$-!U|f|)+ihOe8U+c`coO*JY4uw#Dng+0g1Au}SfMRfcpfWgY21tbkG4_Z<^_W2OoB}oM4_f{ z07PsfnV+=bFHJ+xjvL)M-w}ywrE+Qxrt+)h5w?w;Hu-mq;CMecI_?LlPW*hcitlK~ zcj5ydeK60A_UdZlCoM;r(R;HofL3!eCYaIu{`@}PG~mTW5L}WWDR4A@B(Kj^*GKWX zBs$T2AefagAJ-$%dnfQq{n65CgaU+Y`_Y&z0H8N{Ia(@f;I3>)(U>d)LP137e3{7L z6OGAavB&7soXN;rDsw<+e|#>}zy$!VAix@2+{h1Qu-5X|Xsxp{1PWF=mV;@y%fCVb z{?6B9u20j>*7lvU83hx!D(NIabC8lq$B~A^y~Cr!jgT(nQQOXUgYlO;2I4=M5<{y) zyPhWcKO3kM9!Cw9W%0dtXIX)qMaZ@a@*y|uzao%3 zUe*K%WQ>r1wIeEHH|$vqDP@b4M{flnXA^Q0A#0F27l1CQZAj|l1b#u54LyLxbRuyx zS_wsXwR7lW<}XMjnux)tEaVWvFR1Q>rysX4i+C88Em_16l|{@VNX%%p663 zT?8Am?Q=A(FJpv^Cz~KK;}^si`=~S#9LINQokuE)&!XHyw|Gd0!{`L*_snuM(uiez ziD4uY!vlujJ_Mg(9Kn z2=?QdLfc0#Vw*w$7caCXLtql2UgBlhz07nRZ?-SMlLu-9A!MtHwzATzT20)*{9~v=Ak3C zPgT9(pZ_N3H&Wa^#tbo*lHH4jAF6{KB5(?LBPuPD(GE&_mpyPZBrc%)3{cq3t z#j=Jg96mz?c>lAcmG9EK5%D8#EDS)dCFBM`!W@3i4FN4{M6sKSWDK1fgVk}m$H?t!knW4rs}dPz@ruq}7#aS7X0W?A$owswKa=xo2899@6av{bw86ZSK>_d5kVpzMXbwD{ zZSUZkon=j)KJ%;yG~S9Z3@2|thfWvz?@(*d+1UK5Xhei83JV7_*^U5OVb5nKOw$N zC%VuY3Q*blV3bB;>x)@BuIaaWL>_m33 zoiSR8O67NMFCf2%iTM`6Y&`Y^b%rCQYti=%aPSwQdJ0sHU3@aaY#F4r^l6gMV~1Bg zt@MgC{VNE@6GZ3^EOWGtu(?Mnb%}|Oq4yzdE@l(NWAkMW-MxS5^I+vC7@fHEYZ!se z5`x5xLHJ`QflY0(6{c|5jT|;6()$(C+dQOu@kCFMo?Yf41skm}^y0|F|Hi`O9i%fb z0@6QKYiR*iur2loAXCO!6-NXqU;J0q6iD^n|I@z}*hse^5wNBNt8Pt!Nci0(zKnQB zS&Djzyp$a5}`dD?2t zRr_((px;4A#~#e%$!^DgXR*&TowQnD7+&7vs1GyJp<@Bmj9fA-_A7 zAfdGkn#%l{r;3U$pupYqEOZuzo{Ao%iav*Jid_^d71dWNx(zGXb_XmRP|?M-i}Q)} z4nb=40y%kBh5a@6R)CIla{K|@dUCvwvm0=BP>x{s zYxF8LvnODS7iMqaHO~pI;Sf$RQueisr@+vUuq$D<1xB#P3kec4D)1oE{)@%7;y^n= zcQTtp8t(fC?pa3CW0++jSqG&T2Po}HsG$Ot&`<)c=XtbFarWRZ;DtU~S8?dl`Z(~| zSq`la5Nj;-JV9`NkbCguHE6wrwC0nFFHa$@p$}1xXaSWYw2OfHGa2%%AqPXx8Xkgq z*{fi5BA`-?fV4Gd#Ehv}!QRgDKVS`l^l~D-Rw3=}A*~Ol1?gYht30jzBwH7pO|)_* zkzU~-O;bqM5F}-2MRR{T11z>QH6OX@HjBpD`3Tf_W^}>2S9*#C|0nyume!j z1g<60;XtZmcGpK0Shm}{6xyyQ*oBI=6!cQ0Ueg_YM;m`Yku2CGtm6ZI|BKH%h!YZX z)IXXl?MuUrL~Wok;_G_{O197|ER9rvY=Ms=kFViQj&(vF>oKG}vc)>zdjvec1Jf3H zyowQA;x*2Q8J|-gt682C+}*>3(K|?9Kayt|8Dt0n@dG4 zDV!Q1zv^KRi%$rJoM)d*EVNuz{EiF=&)L5yzPxBbJNts;QZbdQJt?czh+q_I8TlOP zrw+_*z@DM9NJs!LJ4am1fbP8rUd&Z!i$h5Y~1!Tt_T%0!FaJCpaT!tYvWS&PD-5bR96F)4g#6~ zQWSYXK){|S*!e;c@?To5d?5(gZ>R}pNbc4UpTzlRFavSg$uj>n&i}PJE(cYob;fKj zJHbk~J?y9yw4l~ORW{`ztxj2UA=jKIYu2dB3b`36sZB?HAyS)$eaa`bJ24cgRXhaA z6vNs@YVTtNEe#+r&MRZG{g^ZW{8D?1sLvp3%eW#&S5O3g4GD-F34!kr>R2-}U4y{Q zsGBr_?Hsj+QFZwUOu|qIJc|VGfei|QEfs-#o)rSCsn&yMXnC_mBB&P;^?gKb8M`F^ zQ3PHbAdoLgt{Pf9fp>|SrhMCx+=X6;?FO1x%}Bp?^evC7&*}EQftnD;d?92hQ5*KiQ?dNA>7}(FV!InK5HZNj7A0yaBJx)TMiAC(GsFR$i;XZB_ z)O^QURXss%R6$?(;vx#`xbe|k&5b}+66)(Fq+9Q&iGm5ePLoh{KlqNOyFW$m(Vc@~ zfbN;H|G_wg?t9e!cM2!rdx%)XUX9YccDmP*qP{|r@d_q7bcX_TZy;3L|4R2{2|6hs zT|#w+X3tKro-b&;+IpUVpQ~+R;gud;U=SuGV%kJ>i&H5k*(N3sEJ6Q{1f>Dm2Iy1+ z^fus$8@=cFrTzt%yP3-crHyl-fb+>kk?<8wX(#7o3JIZ>q+O|GI6O;2ONi`x0r?v;W2L}^X+>a4VXe;-{m~k4*g^N+g@r73HkVK00(t`!%ZlWv;^RmGob%$5T z4>a5}TQeh2-xBIcLe&sRXe@G0P3SR1Ga>XTR+}E7F$^WddK-xGBkAy8Q_CrEh9Vxd6)Na$Z0*GlMW##$xO5(rla z-N9=fp`T(XguX_JehJ$XLZ4O={SSd-MsG~E_p*R@+Qovpim1mCwG|rbp=t>=NHRHJ z#{r#OKPYj)NhU|%k2P;{@D0NVg1KDza<-dH3esvKts_Wbv=GN~$i)-K zKHlDwQkyuKwk5na$JmGNqCaCxc^J_d=e`4L9^jg@Wz9f2gXjO$Nn)L~lZJhSbFSeW zE0oQMuhh^T+o#Az`W;Y%mQ5GPOeNY~5vRR$MCLDUmrO>jGmK=9R^5i?H53icc91q75SgeH@U&O(J#_!zIwByuRW>H$B& zClItzZ3H6@E}kK3w2ZGg8I6N%S>fft3MX-e)h9|DX;75H;S+;*VCiw=-T-6@A)f{$ z_$~(dS{6yj7)2Ia7+F18RAA`Iq7?*g$6%nMypu43EMDY{nDH^xZ$HcCKtL9|sk9bE z+D;*D>><4#xv@Cz=?H5+$8Cn8RAs*s->DA1?-ag2m^s9ZGcnmd5BMUei69dlW&~dv z@x6BfnZ)-~E9`U5P-LOGdkA^oathOJZe|>KssRP<{k_QCxK!6LYTi;)!(yl zI~HolNioA_cpDVYvQsu3diyAl7|WXiyp36qyMKA=5ca=&Ivpt1<{f8^D6Jf#-Goml z>Q0K93PsSJq)o=m5|V)8di4xH@s|?x$A)C_c*HN}{-TKQi-v^|zcxtx2Z_YDDh7cc z!C;j?V+7(KQN%aEBK9WM^WG-l6M7CQ8YC2jvOLu7;2z@AfBs9!O_!TChO!rLVL0vM zpj@NE=~@EEjA|OfaA{0vZx%WAB&xj)$b4ucBZcC!2!vO&B>-}aWhF-{8$i06% zj8j;AR_*=Isl7iFE7(7?P7j1ELE4K*i-1(RE$i$b^_D%-?dS+tZ-VtBZ8dVKTK42n z6Oa5$5HE%NwmJ{gjNssnXDIYP&qj?XqL- zhXGKi&nMJefl3H~y0X9eK2JC*aLT;?oL9hk(E|KP)kfDUi?`PgR>A{Zb+X%n?sW0%&?TGO#SzW)I+ z$~GZFxQ4Zztpm1v%Y? zJQ+O2jfnxsI|%s%AmLD9@*hhv?-cQzhxirPm`3VCiyKqM{Yq5n_C>ugmm7hy2|+)W zi{{FrQgJmPObvAm)#ptr5a(36^*8E0e&L+gEfB>Eyf~Nxd zd}|touz8vmfr6&m5Kp~Epmcstx3BA|SQ_a*ffY*r#dU9ybvN7R5++eCp^YGn%^2g3`-o6Z96D+5 zP)S+MZatHWPKsE4(&9$l`w)-uCg&3%Bk>DC^C;2O6*M*a(nkCq#DFqT*(qXGl5k1F z)+xHzYE_K%sbW4?dly}G5VahWSxZF0OCg4RNJ3EsoMluWR znas?)f2ZRlhc#Nv;LkBt($#R;8$eW@0eY^S>d=!U^lXRpO3T90&tMnJ76Qt&PHpi# zUNl~MurM{R_}n`F*B<4U#(A-$Txl3YLCHR;_o+D7jkhL~uT}*30;UXH5(d z9P_Q^@~n($$60=sIs#nloVmxH^Z0S^%s=j(1;@Sf=5g=HE>tkX_qUKpBo$_v#ofmvZ%Zm{4&Or1I3*^p<+rxjITA5b9$>>8^O=+0ZbEhQZulnhq`h_>)ni0 zy8EA7PbvFzYrMjo{>etHnlmD2c+Rk#p(BP3S@9|U$KPU$SktIfGy)3i<;8cI@wW3O zCMEGM?nj4aBwu9~|CDZ8he5@~OsKd^2d0H`;u{%rZo)jB!?gl%o5@0QHb|C;0;-P+ z1Re+t&FEwnf08~zs8G20Z^Zg4FFGVSKiV^G(BP|b2ImlWC;Z%5tS7!L&@(OHI*dQ5 z`LVvK_>1uVE03K|1No*^6^V6To);TXf$ymR4V=EDKSU62lbv)^xDB=~{4dXHoM)|y z;PHldN=p;J5Y_F3aLJdlLjPp5xGdSk5!$_Z;4shn=Fe%gQ2Z}7T+)~Fgr)}Fbd$Rt zRFRjpCR{=&Oi4An<)jv!g{R}_LqI{+A%;Sn=cgnmK)3=3*Ay+z z%Q{%tXRc{AFs)=+^5vRKKFTGxswMYM(o1dzoLX{6;W)E+6=okSS^`sf(}IPJriF|$ z+pjXq57oIXz zKSAVK`qAIOqoG7;TGHDnYv35tIlQTN?vJP3lS$|QB z%`))|x_5#CWt4?|nE#=!M5Pdk7G{isJpz+@qex-9xUpD3*~Tbr6|vUkV!3qeZSwmy zpT>xZDnJ=l^r_fPj z#_w_)U9o!lHtKdTyc)NDac=R)&r8cDj78Qoj5QQ~4;AVo3&uKiYY=1CYGg5(jM*#R zuR~X0!dLrz~#qHg=PJ9m!S-k=jC|BUU)#a`t{HKAz`-R>}>^ zGT3j+c@M~N4bfw;xb?)QiQ>d}P}JJM;Vv&h#UHR!W1684ci3P9!^D2u+M+2#l$@mYEu{`X}ccEKe`2pSh;GzKI_-!KiLw z10;%h@jdvz4tYW!%{Y}xPcvz8IfEH*^APE1tq5@2aE=iKV6GsqKr0G18#g+-R#A8j zG9Me651g~!W~3%l(h;I^$yZ}DHZIwW*Dz$_i*2_I5W-v9MugS=D|hy?AQ#q@tn4Q`37E4Tgsm zwK1>nooZ&SDr%9BU)AJ0g0T~Au$LezRh806N)HxwperJS?U_p8ysWaKQ_R=^Y#jKF zmJRkSfL0Il$L~S-juhnDs~zXTdHbfC*lVgAVk8YP|-Q6kA`c^`$7bOzqt#)Q^RX|EpF|7sD zL=yXoPQ-Z&7-`kx7~}V6h&4N1Nxl~b5WE4w_kpj+je#H>g0G)hRy{_H46in?jHB30 zX$4TQWHp(7MDubDc{u`Ju8bS?xvI;{L7)>}O5;VR<2fH)1YUJAmbso@6*G<^{)j8T zb|*j7Fs{Uufc(NW#?Un&VQ~!@V@@)@>y{O|00`hD5#hY(R4OZ7b}Xu^U2g2My7rJ` zunj3yvO+flyvQ`ID^jgKsaARMu2^@hT0iOObfd0>*{%45(!2tB%RBi5%a3S1Xlp)z(WgPa95~dEVtv*w@ zN1MXMFonbLU7ErKG3#oKlqu|>DO`-9V+sXy66`-~N}%GqOqg@D%_n1X$4>TIC1JlM7pzd~1KDy@HyM zO+!F^){vuZz!Bb%G(>J10pee!!d93ncHo;I-{>1Gl?{uz2!0pycG5}9C~D5o*(q~} z;?ki}tc5}rgQ>Jz9d%4(D^27oF%jkxm}>^6atnd~Bi7+8W?r(Hm2xH|Ths*Bm-!hE z(L)IBs)iiFa#<;3a0h9KWn`kaVGnL4+D3b^M=ETkeqm#8!mDr?z)g~_Mwzor2_!4{ zSP!`QNxBnrKmd|~5x1#~HyqtWzd?4pOl5vXK2@Bxwy-hm5CUOp&Zq>N+APY)Zp*Jb z^7=Gfj~hRU*h2dlCD_~u!F#HEF(w&#GK1T7;SjTULRwPM`A+hY4Pmj1fcX0kWd}32KHu*dOw#g-Nr8r(E{BW7_ z5WSVlp9FuDu)IBD@mwrq^a~iiRoYQEfWL^9G7N)!>x#5Uw3!)gNS2yOR}F}KE{J`F zJRi?Lv9Sf`q?c%5m@ETHLvLR1_% zsi=la%ck657MG{ZHM=z_%wbAbT#mZ0Z1R4HR~8Dlp(8=~(~>wB>og&%{brUi0k#L@ ztqw_I4XbJijP3B`2ab)h8lREC7Vn-D?VIkb=E_Xlx6W77xzDCKNnbj5AC-tiVCqM@X`{Nd~i|L2ay-X@o|8>$&W|n!gI+-dyJG*&9%tw0GFU`K|AmgN6 zbL;-vjnXhYlWxq7J6$Dm*{YXPJTVn?9UgxLAHBd}<3=;_O;XBlMbd`jh(MT!I!T^9 z$BnVD7^1^=;ty8Z`(0qh8aV(elU>cJ4+-(fwC;qdZ8x*J{B;W@bvRsNLzWod4H*>m zHm&7qGb^_*Ek01E7kUJ_x2{WaIU)&Gt?W7w_OaD|dBTEdk85#*IQq2$w7- zQ1O(sq;Sb=_=xoiN5G9IqI_vUgSis>C`!>bX1%SmU`OJG6NgQ-sH~Lsq9Zuu zmG}Um)snfyjh6(7&+U)5&Whu)S4s9R2YZ!f*5#>pT_sx&e+yJsip@noLCRcBts>sq zG_^W`7tHAG=g+ENLGgK-llUsF0C+xBg;J_2&&q~0u~iPGXLAP(mt4V*R_KqL@COE! z%`MtAyY)y8m(CK!^g$ddH=i&wmz(XEo5hFfOl{AAVgNt<r4 zo9w~ZU`;%bC>bx^IUjp>12fzMD* zg(6f!p<~I`$q~e0oC7Fq%xq7m`+4!*qHv{EMii*FKfuE!Jv{wisP%sX_}lmYt#@nX zf7AQerlR-xKmVWfexGRC(feePT@AetBhYd5o`?6lQP&XACD8l%VA0Y0a7@GHYvRU- zxT^L3mUQV-)&i5OveN6(3e9v?%pZUHm5H%sSDy+k_ajv?<8sV&r(B6C5GBHQf0G9( zC6qM!m z%&fF<$v60%$9=vmIX`RFJ2i6+l8o@|(>bZQEY0keiu5R6 zPW*XU70ffLTFHV4VQz|%3MDbc*n;$;>MvlC45R87()0fAR^j3;_!P0Ok=1vEXMe(B z>`G)j%bk2BE3I&?i>Gq(eq;h{;CuahgoPZ3$$Q8BIo)O9Rx@i`;cOot=LjF4F@P zAYbC1FE0p?-T!#i0+vm9p!$ET7vgx}B8?VNOEyK}s}ZsXsrrC|wOz_n3ylQ9IKAW> zhJ$lBPU%{hHY0V{xRHJxrIGS1Z(+-`njqCK_-{hlf?^v&Nj*skMJhqrYtr$k#p>q? zWw?}3*`_rG<B=ElDP=~1R?OMgq6Kj(!}tm8mK>^TgZL3Q&L2jx9I9%9QGT}< zlkumh2_LZ=6%ZIiIdd2;$s-tC8#9v7lF&zxDY4BS$uiEp7E5==hYq-1*d7)bDdO?v zwf2}sB15!)pX1|DKAvx$SNwh&J|`8PP(2k7HTaAWYhv+Bxj5(>W?G$C!45+555)PB zgCaXwC>lIOkaHwW^U`QCF6WIwu~9gN+6J)VpdKM_SQorZplJ9g)Q6AbHU?DvET>i(XpY zj=BxuS~c1oDW?y`5;zBlhFHFZUx#B=j*MtDE~~HvR~^HrS$McbCvcw>2MT6)|H9TK zJyUe%0!DzBkoB?-=U9K|^Wg=aTx=gg>2k*pmo$Q?ML>|6%c9Ei@T@gr&EEx8P!gC6 zAva~A#t}tcWah@kq5_GBOYaAiecyi8ennHj+8m;Yg{Gol&MW@A4!RgAC~^67?=fQl z8eh7Df$ysUusR}ZEW#Rkd0^`3bdcP~S5`_lS=HEsMv`s>Oa0F!8rk&)d*NM9$1_b_S;$L^!j{>Rfs4UF=&)#$y5Htnzv1++zfby~xD>^>dl)8PL3Rz>M&;nK#` zh84Q=8vKE6g-ec6CM-uYcSKvVXo|LG5>T=M*ZDNKKX2k`$R_&_L@0=@tu%*W&j7Zs z*o$3NdfQuz&hr|V)c_&{Ecq0I^{Mv2UXxZhU`Uwm~@)!L>eXJo|g66GUMf*bkjn=8U zSuUdJ$O=7zrHV%6S@_&H_1;k?dMtTSKt?K2zSn`S!X@Vk^iZCY*by$lQ8(Pq@p6Ou zMb{xUldjkn`v)QTQ~(R?9%|k$d@voijNtGCD(%7M&gFT%03VPrpjWCIP>0f z@Gm=@*P%p2VECPX*wBm_-4G)X|D4Iy{hh}>2H!LqH?DB+T!1zSJ&2?u0|~9nTcq!L}A((JVTBs6v}~#?8M_Pupb1_0Zs?a#GV;p^xTwZRpc;w zP998-B>tTUk1(Z+gtjA|RRPbt8Pg~w46>*H701W%VO7QQ$z-loRoy1%qx!gvo4A`} zt&|2=__Ffc@MTqK-F32hqlNc^oYq*7Uf5zmb`HN_pY)!Ie{#dQyCU^|tgauiZZj7|eOh72>YHAT2ORLr9M~2{u+-AkfPe?5GML|i(>XXw zcQ8EjNnEuymG7-vyr<#8^7O(c2g|by8$@D#J5`^6e@$ZSYi141=u~tH5&`_ct{Gmq zJ`!G7mRIjnMxW0wLkvEdJwot+v;*FZXF71&20)!>9pnKG_{B=li3A_H_h2Ucc)n^W zR(UvTnve!5Ms&jIiq=ZmFh~q6jSX1F{P;k8NI1cPQ2Qogfz$8Zj^`4Dg8dfa`(2=e zAFoy0+-5g%tY3JECo_30BzhuFR8#366mO-p6i~p8#RvDg z>Kds-UA`D4`?cyhTGJ&FgU?$N@LvJaxYS5AJ2?_Hp`ia=##q~yr9!E0Suw56k66(H zL;`j)&d7Hg)<#||4|QadLX<^izJ4`$imGt27CSzULa~RPWqbw!q4HWGuH^1&y)r+G z;K>$hp2x$gKWLvl}Hr;^3(zK~kj z!>z|r_rvRQ&`2a=si!^Nog(zpE3*tku~6=Ss?Li$3ctS#%>X%$%yfe-50*;O4Kb~I zV2<(d>~eZ&>>6wl=rAKYsl-@!Kq6VI*#YVDA2@2S%pJXAee1aTM9JF2?GKFg@p%Ic z<}M$zXQFz*gIqjK`D{vWWiUvDQVaXJeU{~u_g8m-vH11nHandDz?bX~)B|rYpJsV+ zJQ7-gnq+5q)>uRxiUa9SI$4(_Lh=quPl=>@H${o`;~_*3s92qU#M#EtX*~W2bt4DJ zDahQ1(~i3&o5&f7vyjOcZj}NnXB196ZpGW`NAZDE^p*l-9r!acFV=S#fRgdO-vN+g zx6uXR(yf#zcBuZe)OO4k(h+mw#>-czLhC*MeViH6z<@(3!2rQiL>$N(c%fT59kHny zud6Tfirhmk62+7DhZu44qKzXKAnrlXxduT8NgtxN8SR0w>>q~1rJeiNM!w;92t__!*0FZ;d)29`o3xFM~xfXqU zUdBes%h*GYVFkGA%;vZpv93yuWDQ6Sm-d$B(Q3E)rkRLXI97Nljx$SW-G@uh!A!3ZWeZ9mevQc-x}C&Wrttd3F=`oRBr=MiCk_TT+ZEi zId)?lnZj<2f3X{57cz5@MHMy54KHpKUR<}jIfivPT+%4Kq;7R6*J@0e18QZPQn!#tElQNDd#KDPIv=ne}k}(5+6o{Yzg!j}lYFqs}UMNQdUh9?Aku6C9)M$d8se z%FOzuuqE^6=-5#;eN3v1Q@9RNt8gj%KVCT~-&Nse#RtZJmO4$|aLHy(_sEEKH+qRP zoIBY5v;HXjhsiG`qg7J~V*xV;97GjNc`AP`&6iZLr>~H~!%UnlNe3S~H5-e$)yX_M zytof(k|eE2`tp1@gx?#bCD!tI4>ei8h;=#Q+Rhx`CS1Br&KjlIRD8^cqDLCx69pK| zJ|L(%%G)txsq{`$mWz4dUKID3$wGZYu{TPZilLmnbn6IpzGIb|x=>BUZt@7`irskm zA0N!4+r`XYig^?Jh27yNspHYj#EDXI5?rpdXKY0S64@tDpP??7wk-Wel00=F%)V|r z>-hiSX|%3yXr(w3hf21q&f2^3@jf19fgtG;eU&HrLiz+4*iN!5ztqCEm?Lx59LC2t z1iWaI<0Uvb0ZY9fmWeOfwqwl%IkUW`kY@te&6C}J2xE3E<#Y6A@%&Kqe1HkyiT;4X z9T07@tI+HM`}mzMffIWeOCpPxiup}$1awbgC4L{HcRHedI+EO&u|zd~4~QZewn5Ba zP=F-&*an>z7!I;09(s`w@N)E+Ne!C&PNChuxbWj8F2y@J6Pw2f22P%P?k`2As8&@ff(7*Xf zUFH~oGH`+v^HWsqnEn|ej&YmJtBdCqX03a?sHL5o-TUZ+5eR+o=seH|rr%PObtPpD z{3OUhMP2zQ{N>C`ItK$bJjcrGid-cx+8=8q?)aJ#SWyl|8Z$1s7JrDh4tP-e4bwJ< zQT-Rv%ND`pWXrAp0Y6}gKl{JoFQ=CAez1`m|8!Kl{|*002n4bY)d3tx2~z0l8&O2$ z2^DXoQldRO)exjOc(8=@_`!x3Gwv0lQd&EP__ryzUy{t};xg+hd($@Rkdc0Y{6|F-yp^OFFhT1+Q8 z@)YaF*??&AT;8Qc=O8sLeq4|IJF*i(0v6zt&w0ob?#<;YNOq%KFE2V*mOUQJD3l_Y zPzd?>p1Rd9;;#DvwTbssj=&#U;UoY$RQs&Z;ZN80qT=(+Zqw%jec@^LF*zVLG1;LV zPe&a_9oJsllO$`O*5^s-KkVTeZ^%vZLy3SN5zK$#XEG)v@RKh5R8vDS<5PKr0)Act z;D6&s5Gj-O@zbFuKd!2Ds5;W4c76&kg}A@Q%|f*EeBw@*OfI6x8|ILAQh+?Dw7M?8 zFcDp##K1rQgC#37arGlJ6hAnOoliUQ#j&V7r}xz0+8B@&)yphH49?BK54@D+MyJmN zZan;LhoFjT3N01nIrTUd4}=LuzjiL9%YF)Id`}^#YaZ&iXik4THO|J+#DAm2GJ|!n*0SEps2dA2DhT4j@KH zj|?QaC}h%|JL!pcBvfz?!cyQ^W?u>4yo1Oeyp!#$mYsM9JCdRR8&+^mf9FpB#5)Df z9UR38&Kc$0!K1Rk9m{d}=4SLY`J8ayaUkB8&k6S(%i?|c9K1hiEFYv?%63U7>yK`u zCrp8g!=xto6g-aam#t3Dx_iRpT@dnEyiYv`7AM(cbTo1oWR!>rl2alOxap*uAE5P| zN8c}=)GnzIr&y75)sYn{?Us_wR>}^HRC9Z_a~6O`OZ_99jzPymp9H2G$;NgyTfPKAxX*t8k^P^`f^isS=8^l{11jYI%0{}T2rMcxEmzCl)e*Sr=+?WMCyLVNoR#j*$voKY?g>-Q zaL${E^1K--p60%#h9v)&W72Z=h^LUCF!x&^OmrGT3$If-Y|oS@_@i}2c7$iZQ}*&P zU%c%ARO4=RQTj@zzTmX@{+V`K9^>7r4jbm8N5-#`J$#hDLzu4hw4)%X9G*j_=Cu}ZGF<6xp&nEfRux6@=CF(xX9=?1$}vio&TX{ay3BPe+q#vu zn~k>JFACLYZ5y3!)4HvxbKRxbEjm}}pKtShe?I4Pp8MQ~Jc4cA_S>s@aXI%n&pDs- zIiLUM@BIk6wGC6S)F%D-I;Mnf<*J8EKgzfk-ROXD zvxbn*V_Q_`xdGA^M5S~DE~_#;zH-rTfK4>SzC6I^BYtwdKm7r0eF2_d=jq(Z(m%YO z=rcx^dOi6S1nYaGmspC%4gv^-86BW^e|-Z}bpiKxYYq4Ea{z%}uE#l5UI7_JM>FIf z&7chIFslcrv9gLo22}E?%uLqbGv{&miu9T0n-3Q)8^enGFpd=j`vb4-!d!@btlSk7 z8-Mqm$MV5)oUZ^?5o^L~4W|o@$@qODFBWe=-%atSH}yc_Rq*KpeMqPl7ZWiK_W!mH zSf=R=JhPTfW}n$gW}o?diY?FCy(w3}ww*49zzTTLmFNL4hi~|+TKbm3?*tO{nIXjo z9|8_^fa~s({sU|R`ZvMZ-d0Al8*sFk&PYbc3gf#hx%S_Upb-Ie|0WDD>d@gkYw#Vz z+f8i^{mBqcgpuh(dHCO(;9tMmzo`dNCUqEP;wJo*xU*kR&ghr`zq`k>f(XDi0FXiW zD!oM`Yr0vhHT`L8Y5l;_ae_~)x1Yq9NgNA>(Pay`esKqY79ac+<(Kwx-$${NxJea1 z@H-2h0S+upskBpuRtXS==_v-tsP_jS+lf``QwEE^4cFF5&B{eh>jO8%esddaW&03;_%Rh z8Sf&=y}F4q=#)OO4FeUZPie;u^vb@!!OSuKBJMJnh;U!1u~eQfKe@dbq!@>A0DzpI(rG-u!5tbrIBjt zBPPu7ZmoU?!+HWn&1EUcU!FrrnBL;$N@uJk3jajzhwn9r@+6Qw-DT$eK#xf(an32P z90u3yq78%<5JTDqQnUd!2rNv`9Ki0=lNGpxgWN8R1w@A~F~Fv|W|#~d8Nu`>ws>OY zsA1slNbu=R5wHeEa#NF}ZIn)yeuR;pAV%NFI$HDyjsgU)3zos$4s7@`EZwPosyR@4 zKgfvjFB}mDApB$Z5Rm@B$H<(MR$vOKzo-SZPu~Vie`gzImo{*voIRjM#(J+Nu-x=c zz@043TtgWf+F1ZF6yIXyU>Q~f*KfE8?{FA%{f2cYPIEP&@28N5jx1mEqtln- z{tP@}ec*L8Lt}{2C$Ptz^s0ew8TvH$n`|j;@xa|=WVL9y8>p@t8+o-4> ze_uX$4YACpH}_qErQF&pPJHx=C!ar4i=#8mSbTYA^ZLzS&A%6`D7ZxBzOv1Sn|yWa zzkAO&9WU>jh9z?blH2@qbo|`fOsBBuLQTG@B}6jbMnB65$*LU~Be|*`cpY&ORJ37W z9A2!9_DhUp!Z_+VFae5Vd3dAN*MSAl z%B!Kr^mX8CnV%t=SRc3=PxoFFJQ~a!-hAEWujKO?rmv{YU_|^>d>U4Gu#spROl8wH zWJR`t)@?y7AV%sT;`q4``*)3`7ILN7+u2^pCA2>B^9#U&7*c zKV`sf!;bOQOxa7AV7O0TP78uP)E`>mPwtnN=K%?-^t@DC?NQC z#4B`hRPh5R=^OSh(vm}{>eS!j(KI_*`V2|`z}V@J*8>wQ%VKk7Jv!gE4YY0AMqS

      w_n7h%{XVD3ReX>~O#Oie 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 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: 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: 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 sublcass 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 .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 .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'] = {regex.pattern: items_schema} + elif 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: 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. + """ + 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': 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(): + # 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, + '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 .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 = 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: + if 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 isinstance(dft, dict): + return {encode_default(k): encode_default(v) for k, v in dft.items()} + 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://pydantic-docs.helpmanual.io/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]: + 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/tools.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/tools.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..7400818b6e962594bd911f5f9d438e4a83470704 GIT binary patch literal 64000 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 IH$Vgb148Shg8%>k literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/tools.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/tools.py new file mode 100644 index 00000000..9cdb4538 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/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 .parse import Protocol, load_file, load_str_bytes +from .types import StrBytes +from .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 .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.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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/types.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/types.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..86514402e3c84046840ebe2909b26bc02bdb7931 GIT binary patch literal 354816 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

      anYj78yIF54_#JL@GZ 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�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 Any: + return type_._evaluate(globalns, localns) + +else: + + 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... + return cast(Any, type_)._evaluate(globalns, localns, 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'} + + +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: + from typing import _UnionGenericAlias # type: ignore + + from typing_extensions import _AnnotatedAlias + + 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 _AnnotatedAlias(convert_generics(args[0]), args[1:]) + + # 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 _UnionGenericAlias(origin, converted) + 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) + + +if sys.version_info < (3, 9): + StrPath = Union[str, PathLike] +else: + StrPath = Union[str, PathLike] + # TODO: Once we switch to Cython 3 to handle generics properly + # (https://github.com/cython/cython/issues/2753), use following lines instead + # of the one above + # # os.PathLike only becomes subscriptable from Python 3.9 onwards + # StrPath = Union[str, PathLike[str]] + + +if TYPE_CHECKING: + from .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]] + AnyClassMethod = classmethod[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: + for none_type in NONE_TYPES: + if type_ is none_type: + return True + return False + + +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: + 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_) is Literal + + +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 .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 .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/utils.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/utils.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..a2578e3b264c779def0b4c2a102dad036ae5b75d GIT binary patch literal 305152 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%0DQpQ5GiD+b~Pab ze-OGA5X7)!Mq0Oj0L|0R;Bwk2qJ_L+HGpXtYDOJi4-x|ju>2-R2;Xtpj)3j*lb?Ei zQHFWxX}G3Z5K~hvNvCNadD(vTsoLMA+kePrAInbDeh3HwuKgdXBd%2@gbqF{3_dZ$ z`kwV#h%yf%?MdwFW4b?Bs*IF02~Y(uk_dQY-xe?R^1Hncc&AHSY5IKf*jDxqA3-xbxWke`(@F`!G|D zkjk@R7TyQ#acFQaQ%O!W7T)eRZ|;SW&01X8fjvU#o%EKZo?9TW!g*?l^)(Fbm1?Kz zGJJ7=upTRa;KxO&*~xzf6~;MpMoKP^5NKff0@Q3n?V>`vf5w+mru3zOHFxeq^NEG2 z-$Q~yp>r{Mr=xlT;k!|QfF0M<*wdeNlF0rLBj}GH<`n(OKe<1a^yky0PTYgsVfw>Q zex9m7(vW6RuKuhzxj)WO89{b$&E)+_yaVX&MPdTWUl+P9S%YV5@K)I1eHj_k;DL6r ziGq#dp$9b@7@UTZHJLc$BPDcy;C%9X;?*_%hQx0)Jq!+w$@)zE3yjcuY2_=JO_=jf z!l8R;M<`QKf?t@OVtG?!>ah%_dB(w(tArgg1)MZ9rP{8o+M5CnuOWZ{$Sl)rr!;$0 zw%IA$yeVCFN|z^v*VO@2PvQ#Ip}&{s%+`i&f@Hcpd(!QZV!AwMrr#E&KJ^Z&1r@`; zUbAE14l6KBO&*J0cg_i%r#O^T6(86=1{bI(^s{Qf1t|?n)DGwZH!NNa{s7wu5alec zF^cy1!*Kiv$9(X%GL?Xeg|%N;YWP-aK4=;dG67++TZ?FC_{E+A_S9p0ErW|U&=B1a z;&ueUoCVkVnu!;wz%PSN4d8?VW(9`7YofJL^eP#CSM+a**kL{PuIOVrS_a+~{fv&5 zQFld)>2CNc8FE+jU+LU3-md6-bhHdM_8ByQ$z)*I8Rc|r5V7{yrehmqpo|~89=nTH zzP2VlaK{CAKfmL3!_81d7D>^OlKBE_!9%VZKCf%Y5rf;a^qmt+S>~3X z5WTU_WZ-Z3P7)5telg5~wAWmooqRWTK>_EtAN3&#{v=hz&ru*DQAIut<@Zt3OKgRB z%^(Hy02})Im(t&j)q>ev4P#X!Z^^}q=m^y66y=S*=)rKk@JbvOqsuL zOyUWe!3p%7rhEnQ{L{0rkVO9rl@Ix!Yr`7LIWyI14ADYs+gFjBk(S>%=P{ti=^LiUd*+LYwwNX zRQQ(FK_ep{X*NGBEiqLB+47oX*10kjN2DK^MLw~OGB7xzXinx6Z73-BdY8!EK zgy$Q?rh(%t*!!}KXK0DFmdmc>Ttn?8Me?4&vi3)Ti6)qc(8K~_GVg@Rj zJ~C$o*p$tjfaErk_()0ByVwbEf;nqsRz8)M6?~c+{>I_AeQ*QE30v6UMHC)|cYTid z5yNjuOACin6jpkU;4t9xJW_eiYUX%@Gpk*jQOvC{zd^6`K4@|t?K_2cKPi>T*4Obz z@hpZk%yrnkZYS`QIB{~>i+wM9EBV9)=;(ZD5k0ifLo}P5DER=M;P-_8g{HorfFYse zL$D!<;~!+{GlJrQwTQm8-kb_X^jCEB1$09SaRCbRT#4^0%r^?)`*kXq%Hx>O9xg#y zG39WiaW43_?Fo-$q1UiG+Hi_Bft3g&5Oiq!eIHu3*$PCJ%~ni{hje~v1n|yAX1M>r zpB1hF*tEPIjWi73yA89PlL2hkJ`xCOIe?Qxv$5gtIuUr{QaSE(7m5*o&fy{FJYY2j z$9?7|c^*6uuDT4?th@#;z9*Kv7efMGkEh-8bak0Y_#t3RBLh!>lD@#8pgYcy^FQz# z+Js#PoZ!(5z^1vO;nKUC=VxyV1rF7Qq<4pEx0$eu;Y7(Q8H;g}@09_{vw~?MG_fX7 z3idg?u0HI;ops0wJb&y;(#2s27AWWmbf08DHt_D9yeiK@9`uV42sZ$l2R8)<=(`%=yD zdcl-7-G^VL^Xa`mPUti->x1STZKae$Ax2Eo!Imtpm`%Q?- z-HW5gqtoD2iH+$d$fRvehzd0U*IfY|*a|g(#NiErIR4kgJN^gO>-=)pb;A~nMRQNp%M!Ux+}&7~AzrW!Sw;}2&e#%=;Uj3>LGs|&jTlW2xtN{BMC z87ddu8k-u2hbYasq`08Tk!B?gBMl8xGloK^kK?q47S zkEBDW*{BHynnY1zlXFh|vE9Eou>!>69xq4V zvd=faNL>re2!1ZfxeXK8Y5@A=}h=U&60z)IdoonTs``fd%ZK8 z1h)&_zpf}SgatYLhla412&#he$n$laSrAdwI3NfR$;+0EAdtw(T*(c=o11yqo<7Ps zeCHlca5$3C7PXb#V~emgMyUK&?u zJ{sbQkrx9)9}sKH@Uu_6kLxer#I+EFn^!~aSvjhsFpEr{Yb%UBdE;vK4d$j6)Nv(R z5kotw&m2O?L8oiZD5demuERLf01iOENnOdtOge!7Igtj>4bXN)>I;}Pn&F6VTu8al9zDK`|nKJN3cCa4vxo##fxIo?U&<7YHJC!30ou0;@Kx_rIOmc#u}a za$C6u{4h{9SJ>HsUhHE&e&Y7jEb(<4r()4NQSvZ)5?IrzU(XP2-x z!2@b9m~kOrF;{0{w16832Y3N3MC?RK98o8h8Jq7sV(er@W6leoEUbHjgH>Jg#CtVa zx;bi^upvU==w<`%Of7kE?6I6#d%h;saJ^OVC4xLsvivFoY8>yNY19JQh{@OV#GoNx zu*oWa4;F;U8L5Ayd(wQo{{Y=c=B|8xqU7V~77TAfj=GGj;=q0M7SZwf5K17?2Nts> z6ZhTUkisVMcR8Mi!EkjU%^#ep2_|t}Grc1Ue!(h7O1iEzefR?2GdL)jXM@NL+@l1l zPyJ8`c5^ew3hpC;LmQjX9>zcmo2zr^G3T+Y-3=ou%5w4+tdr@7k^S%mXbOh=XH&WC z3K;9ElRO@W3qHl{BPHkC0M7CP2tOjJk%XAofd&o=CBez1;CUgU*}Ms>F;I0Vv5}(N zIPly)-|M1V2$xja73CeCg_z|NCF3#@{@Lh)W{IL9 zP2($uB-2G2_AdL3c!e2(CLSxit{KOS^w}t$KPc#6>5-Bj23RNXvzYiHImt=LpfQZW ztkbbL%9|Q7FklKLuSj>Fks+Fsnm`XQA@z!utmxU)auN>)#Cuk1bF)Z@#-Z(*65{UH z25?^PN!VHC6!bHxyaTvaM+PeV2I){HDVS9r(A&5sq?y$w!AP1}fl+~BH4cRUa0tu_ zObg`VUDf|l%nFtPE<>Yklo%n)SwXMjD*tr&ASN%i5AfoM5PWRQz^Pz2hV;Tk<8}D_ zV7ExQ)bYm=Z+H zd?@cwLY;IwO$lkSMM@w={J&AcH;?}kEGW(3%=vCAAI)T4-@_?x3lk}S0~GzC+R_@a z(Kp}*6DT8yI0|CHn}x?CxM}VWc;>-xSZm*@2eLpjz!2yR_6if+yf}sUu00Pb+w|VtV4IWdVpk*v3 zG?+}uWFCQ$tE|*hLP1wW?P@V&GYb#cDFfaV;S#KNn>R%hFH(T;%-V#WSf-c+y9sIIV-{cH{k(eX35LHTN0c4qRd^# zk0XZSpazc%sJoTp&fhK?DC}3bK*4Zg>-vDep9vg$O38aSF*2*_PS5m9{Gcre>DRj z2oBp;EUPhJCg^$ZfAnlY3!e7#3B0(1WEI5sm#zgF!it-Ehq2-wChI6U&ii zg`4pOCsqT^e_u@?52ya(X&(Q$6BVOs#t@|3G~P35aHJql8ZFR`;>a`3!F`jQz2u@GIFlca0`0R{N5$J0HL;iJ*4m7K3mG$jbHNqlM?| zMQmf%f%S!7DbCvSoAP7<&cxx8DDk>KF=J%?k;`Z9#MSf%YVIk*-K5#OaUCmadGs&` z4fU1r*e1r+{~g#H(YqTkOrkcif7Q6R`&@?ny#M4Z+Ug&})7ObYMAqaT$vXm`G_mA9keXw@m-!FWe-qhwI-&6HzaW;yp=vbn zG1qk$Psd4O5J-D^juy2Ro~#c@FEm1y!)F-I^@3^FL+g{QDnmO*_?WICfdJ|Gzm<9(^SS!2 ziR3#{r8%exgF3icahZHLbv}~NXes<*9%TWZOdH02T0uD~tC@Ii!e4T(Pv6DLyH{M= z7sghsTkto0g#04)H2&X<5fQvl4pda%`{uC!yXRn&a`fFs`K$&uE5Ps%5Ba~2gw*xu zreMYzTz4gbPF|MkN6%8Z?7t6~7+g|`c!h4{p@EgpSKs?=Y6+fRJ9^Id2Y>8K-HhC@ zI6a_&*hnDu!UhH2w#~vFyrn~MQXC58m@7@I;oQZW!g0nvS-7TTHDGu*&p!VgJs4R( zfdk1q>p^n+NQC6_;D!|(ofF0IA425tQF11(MCt1YtPTGwP?p*U%{`q2=9*3_0P*Rh z!3kgT?WnX8#drzJw^P3)8-!8tBL`AXh|1+(svAzsvhz%od)S=mxTW=b+!sUx z^)E3=lK#{ufCLy5#0cmj0!r`W9|Y(acSrvu=ltqy5*pOB&*EXCWWT%~espHG;=Hn; zJ1zMPe~U!!F|3B1TY(`XV_%JJD=bI+ z|BMXi{yauQKF;TxY)kluk#fi%Mhu%h*_Is%Zdb71jzq!T06jIq;Tt@-8r;e3V^u=~!uh@;LjI*UQ0YqSh>g-Z z9iq*&9g9~30^YMlKMCHX4zyrD5|?C%Ct>5_vX$_O#Oe(CI*Lsk8l0H6 z`->br?pK*PXF=Ec8E|O<8>NKrYn2cDXvN1a##7bf$wXix_dK!odLVDe0^MIHneDe+gr1ZY-(?IKj1sD%} zKLH7#&5?ovydVDqxGHZ9z%w?YO^EtZxbp+}&sm)MiGG-dwxAKSt<)D#2#8)72@Gd1 zso;piTz0}A;KuXH(eXgx7YmMp$t8bYsd@f>--*|WQ}l_v~!Q+pitn~GLQVBMDv9Nf0C@CE=WKB(Yzo33?B6SFZ_!C zFHrdIC%?w2R#^A=J^n$wr)~ioOx=!b1_Q;ZsD7CVd`0kh;-~jg3(<>AUDuv<0TflZ z3UoU>!FS%2`VR~OMzRdMv5Ns^B`YpLS#+IHujRX6-V^1(^2*M_e*drMvU`Uo{;Tla zejhS`7IP8sl_6f|B6!08LvRb9U>qPkf=VER@t@EE#N&a7o8F1b@z(hNY4`6Yk^_PE zf)pMgeE)_))>C(`X|4w;2OrJ@1L<5-Q<`jTy!f%guU=go7<{ZWko8>QS8JvRM)LPG zj^yJrfW?a&s-A;$)|L6VMKhL*I8Bm@*GrFihx#p-rG<$^A! zBb+8=TKc%g(Y-IFo&{=GJ`cR)-SvIwo$o8jB})`k+IXA*b5r-el*qp8`DA|TH57n6 z{RINM!=y2MfBOo|tHC8RQ6BS)`pwqB$UiKu=4RTRKcj*&{F33+KZl-yCbNgX^~^F^ zH>9vLL~|<6wAVa*gwp$3)X!I(cSPpE@c&71?u~rpC=wwXzzru#b}|L^TyAs0kugb? zOleMt$v%=|0vIEl&UtJe&Tteo`qPqkA7&!BWpiNYZZ<aELS99_HvoR$yeo*RE&jbzeq6@B1wFA1v_e;I;b7!5_tr zYZ;3%+;ExBHS4FWZ?sK!w2ZfIQ)Fgo#TCp zNKeh3zv}LbG}H}$Yj_-PE+e(R`n)5B57gZG%Z-t~4nu{*H-4e0b-pcu{+lS~oh~rxIoBLer<=;NH3@gR}kn-~1iaD{JTCz#|mH z#B`wW(+A?kb@(RbSw5T_Iqa(&^52KY6EhGugolTr&8fPPz;CO@cV9@b0Z8326_{)r zjKW8MJTsnKpLYOduR)PR{xX2U+Utf2mf*4Q(f=$i9Q=@uC_=>7z**JMf|)w)ocJ!} zI5!?g^}Zu;S+fFpNAzu?P$R5GkFR|^dF`p%^(KY_v$N>@Jtam1sJeosnKP~@%MgCVa8S}h6zaam=DE}Xo|Gy{yACv!o zg8!d>dcW`Sr|Gaveh>Gw)!6UkE$Ib-+a-Oe!_*H0?C;eK{`d`ef7QIEaMAj6iMcf} zv^BLiXTN^5G3z-vtu|ipTtoZgR}L4`FjgcEB(*uO)%mgt6M2PSK{z-z-k5c`aV460 z^7`Y~{R%u{$y@>G_ZVAn9q(UyJvTAtP2;;OeaXFm+rFjnr}s8hljq%d{1|rKo_0lB zspk>1R}vpjC+N&8aoLrQtB@@#A3kzJ9>eQoahJhi+}Mn>K+)l?(9N1csRRs?tf>NX z8copA+qd$`J6B`iM+-lEVE6#yfy@7ue-Gq=N8<03Tw398zX_i*;lG*iHzq7K`Inop z+JrZl@D>xk--Jg^_;nNh+=S8?{wvDY?FLNv_5%H0X5N>ZcRPR7#NT1Uy(auS6FzOi z4ilzKs66#NsB}ADH{sJJ{D}#t`E>dm6JBV-)h28-VaS9r6YeqLM@{$-COl}u=S`S0 z;TtBLHBGm7wh1duxWR)C6YewNmrZ!kghx&IGZRkF((M$RaIpz1O?agV zx0$fZgtwaT9ut1bgr7IzK@+}U!k10>nhA5Wb-U-9u+oHeCVZC(V> z@a-lHnD81CcA4<~CVbF@-!S136aK`6zcFFX4AU@3BPQ@CrtP~6aL(Uv#{#s--RYz zYr;(?>@?x6CfsYn&zkV-CVat!KQZBJCY)~g)I1X|HsNX$Hk$Az6TZg|4Lw9nxXpxD zn6TW0r6&B%1m(R_KQZCcCj5p8A2i`dP52%YcA9X#2`@5XsR@7g2VHN4B>KiJtF>FEgeg?lw9o^n%VQ=Vd~C(_p)=}QE=Q20xIFbumCaQ? zo@{IH3CB&prYxVCO?CGLyQ8}jUHyHNw(Ct+-SMFGE!f=wu)EQnm=yH9dhs|_G1U=? zM1#pFQ7ZL#;Lb?yPDFZ5_ter&{e6+vUD3!=tH13g46)S}j$3{GRyYCDYD*>}*3u>A zD=X;!$3NXfu&+OXUth!vpEp^BdwTohi6E#W+!O5V=?^D#%O3cq%BHqQ`XVvXNiV3d zCm8SE-WN_JV`g+uqO&Qphhy85y}+~;?o32t)U-wu6>?nBAG2c=nXDvy~IzfoM#{qdnaTWGa{lIBn}yo8Bx22?K`=Z-ER!N?)w>)cXBIrQ$JV*-v220rM%O9slzTG3<6<^#4dXz zP6tnBZuUn5ce-+R7fzSYrV8M>yS*z-B&RKxk(+RJ_jM=iUY$gb8`0-TtggE~0UB}V z3!Cvk^2k7YPqHJ@F&SQ5) zPM%LEl>?WN2|-0aNRh9>^5WH-tm3_4EElK-w)b-p;epSaoYqf8(WWkg^6{PBW_jT) z4>SVv-5pw;2TV>xG}e6!^*7T|PrFlPgWlL*n!JF{L_R=Xl}i!4P8laukCSzfoDQN-KtV070&Fpjwtp@Nib z$E>t6~&fC#W zTH8E*{g)9gj}~|)cwX(uk~72e8ngpanOuLLY#b|4Kr2IN;Pm~tG;`qfFrG=dN||h@ zVJ2tLeg;8^c?d8xV4pR{;lSd!y(`?eJz{m>MNB>`tVCCL+`_?=}(gw0fN4eD!S-}NEH~4g1YO>IGS_Z(PXmdjzRN9v8?nyv9wd-#e+fNWy zwL~{fS;3&4L$jRBae;h96P7m;l~GK>;<9zA-741M*!$K>BGQ|>R<(*Y7hc1*Zr48v=oPfpb^=By9LBlUI*+Ay`Gg>@Nt z)2)lFazSp}B`t3)8WLB*a55gjtfmeV~ zHD_mk48W&}Z>zBrYAQrolgBg!o}p21PaLOyARtL`sOfXcn!^dJClWSBD0B($G%#Y_ z9d1wb>{3p52yg?Z{zGT$&(mMH3nRUxO7c2v%n#BRWcwQFi{Y!*e=6%JFGYsTUJMs1Zq(b z2@}$zC++L$omneJol0ypVOMSDaVNNp(TTR9h{Hg((PTg$RIo2^u7fDHn@$MxY3^gTUG%U_W5C zkcHd(#H9XWkocFe}}(zxYfIkxBmTgL7R^gTzDzE*lM+Ys!u!3~uKA^7dV9LKK@N zTQO&>CDAL;jz_L?gU|^5xaF3io_t0u%i_Q;kddE#;@|pkhbWg;XHR&0oV+j?Y{rtg zcGm_2jwp}iR#SazAh@})uBK(<7Ci?=y~AR|(a#s6J`Ws#*Q-)!4J6su)}QQyY8e4X z=k7M7>lUaj)HmbQ%510wO6bR$^V>KIg7@p9CfyDY8P=*9tka#)9};V2_NU{apM{O$ zg|5@u;mm@tRmRCh&eWb*hK}hSX{vPOAWj{So~)&(2YN!>YJ<*bt5wk3fadtxC0c{l z`-&o}kXwH%{r zJy#oRp?JjOI=zRAy;G(<7TJ!?OBk6ZheH$zJ1J8OngYaHTUBy_=*0aIAUb7E1~C&3 z%FOouo*t;kkeKoEa9jJ7`j_2XS&UhpQbsT1xO0ueRc$=T+OVDm1u&jr8EAi*wc-j* z7EAGlRVkPH&Im5gHHrf?_k^{Jt{k8MO*c?lWU*pxN%Th>Y(181XZ{IYltG?ezZ}`G zU!G{Y@kVJ&mq{;EzzP0enJze-N z-Q|*r{W0ozTZBSWYwf^9+b(OVWRs;8R8}B`gpPUBEsR~S_szU^`ic4|h3FN6=}3#f zNjXryGnN)(Y6D+R&X%5^sB=k2`4U^eYn=l|QIvwoJPv}gz%$T}QRT5}xK!*29sOW4 zRHl1Hr8gE1S0Q#^H8eGCZLL|~SRdT9c~h`i>&#Q7mRm~6oCsDbnAqsP04o;qqs}(i zt9C#P+=3M*s>FQMO#B-6#-VI5V)~iAP%KHhsCC%@0#^#g=UAk-{}xuVV<+<}^^SME zLm3?lIO3WPz6FkD1Lc#wY7@vtI481M?!#zfDvL3rNxSx3529Lb)%5MU5le@58a^;b ztz;BhZrm)5ta!h*Gor0B00{;#y;~~cRnse`M=}O=@RmrtT-rpxNZrBOKz;314VyON z-L+MsKo*nwm9;}Pw6&U6vxR4ykcBS6Lu|q%0Rwp9J3y;yO3D)7^b2P^((^^FLwf07 zYClJyh}&48!wzxp!Xsf5S**=;l-=-W0Kr?%6qgyK%8*y*5rSql&>PcU6#YBllf^v7 zX{jI2hR!IeGu*T=?w#G8{U{I0ry&=LCU_<4r{T+`oT83yv9q8pJUg4n9X6FAp35(! z+3N^C%RHjh8c>2Ss72|{03^^nlq}Mpi=OSRX!tZ@G9b<7M%{RZ?K@^qN6xX0jw8wS zYB}EPppof$4{E|Y)(1WP#!HHtUN_V!T9O*XKU2>v$V}vGXuhsB0Nxlx-#eAtkqz`L z`+%&`XsMX5-2S3vflDXg#^okxp?*-VJ+)P5Z^8vE8e-BF=q-6kxTRvEd6by;Pl7|8@)z;KJAbV1KhN3bzPSZR>`{!cHlTqL=O<(90NC4|p*(2wCk_?7#alAA4fxuDF zb4|T0#~eY>9w6Ordn0fT!@q?7&swZ1IKt}nmst{Z$L*OVt-1Mu!`ifFrqeaPZSHKw z*%p+@vVLnrV{1c(rXvNt4zRZW+)4N&YK*Oi1t(8W%lwnlxmTBV>jPdgBYMLF#1QnZ zo*sL?vK>*x#gfgp4EjCU)yK^Hw^go^c^~7pAj%k*5EVhiQVISud`6}fC$)@+@q-gj zQ)OC|uN?ol#Yp%RZT3>B)z-L_X6(Dg>&h zF_e=_G}XwmSu_d@xkpwMv7h2`3?K9vOq z%!1r*#lJ{rC)awnM6lZ$wl*|u*bEy?KO&M>$;?iztCjnxDMKUJj_)o1~uf+Q-}l=awsaK>)D## zgQB)ULcv;;etKqEtFvkPs_lwUf$f5oj3Y=kDqlTh622#Atrtc7j)78bIzEm%|Qc7MogZuD=$WfaLzH!#-N#RED^W`t_2ba%)AU^K_|xx_!B|N@JC^q;onMSDJhdyr*nwDU7mISC*c- zcGLKBYwBi%?}@jTLA%0yGW4of`q!k_kw{8AG6qG;2HUvYq-@>PpMc7$mpt4B;93n^ z=h}#k$_>cWy=^sInxurhCLE)GMWkl~S%`*Yv+Rwh<%9Ni=4{jH8S@n)opXn9B>Q&s zVSR!9NbLt|%Ps&HBn}#rL(HMGJ`DDR5&MBy0$`%igy|0T=Z;B_UD00|QAkXBCQ~ptnbxQjObIl4$r_LqL0Qr#&y42ovMfqFwvuadY2^(m zF1djP3Z}mqaIGg&ZII%qU+>cxy`I{hO&XHHG1r+vr~HFS$=SHN7Ft6MtRGA!(Dp(( z(``!Yo~%%>v(oJgM|LU18F&(!Nb6)Qj~SJ5j?U}tnE)Kjm$|-3uhCrfyUCVouqgCd zS;k|A$~0hq(!5avY4l!}#TvZFo?cknQfP@bAaY$R1>rQeBPH~fQ{4=nOquT&CRjBDWn=6Y9pK#VG&6~G0&<`8AoseV#t|mwCfVE6B9e^>_-o0Six^*zt0Eb`Z2)ry6XhtuWDG3U zf_Jm=gyC>`C0jC0gw+7!7V@pv{%2k@66Q~OZm~YEV>bo3(EJMe@QKYt=5{j|PPC)2 z5dK_r=`0=Xy#c0sUDvR$h*i72N`wBWZOT{?!}xH%_2N9vu$6^3T67iq5WuzC3MxZ#%1N4`1o(}v@{9}T#ejKe7N)rz2 zz$+9$yd@$yPbq11Xs{VG#Em&YoZhgOnQH(NnIudoEwG>_!|#d5X1Vp+ZZPdqc{@0@ z?PZmwLCp3(tqEre7|ri{y4y^9ne&14Bd7iPH>i&RMPzoHL`iG+JJJg=GAKhAfq z=N&T}=}eR@TRX+%mvhmJ(grF4sE&L?d#qloMXiPt(;tj(S1^ovh^I7ObUKI_$1yKe znQ~Q2Gw?)qLx`k?c3^Da(0rB2Qgl7n)VR4a*6rG0u7c1am?MJ^n1fStj8_+*0uMp# z5je7f@Vki0tfL5!5U93kx!R#jQMNPvD!?Z%H*aRqwNOU5a5!VB)IEmATrMn3|<2-srh zG&GknO!j#c%?~Mg^o(Z@ok;^&xD<9P=4r1F4Jgw&J43d@5~3vN>t8|NSO{`kLAAMv zSS^sF!_cR#U}YR6N7Z#(H`Ud*1Z!GbTN>7HZN*NX{+sMTH<_PFcE;C!cb_k^M-O9a zdP_aOMRpAA{27aUMD74BG0i^zC;TozonGcdde&)0i2f4x5NX93Wof-+9kPtE_~eoo znQVvfXB?pBKyrU(CyXq#@9R1^UYfpL`(ZY-5FW1gK?t{a_~{9Z6#9pOXW+DqfZ?Vy zd#gxvbDavCoLlH2Qu@C|sLNnrC#-37IF5o5U`v-K6~o%Co0I*JD&^MJc%(Dgqg@6v z85~yBaFXBEpR{)3nhLH-G~h5xX%d$9Sb2IuB8&5WE|{o>ij_n}uLY+{3tMl=j{X%A zu?&vz^rv(-)d0WOFAMxswn}Zop^IM_-b-9-xky8qjTgun_cTGhHiet5Dj5Z|2c~(d zb5B97f^%NeMVWS0k@YS(geBVq4xlK=P3_>TvM@A1NCz6s<_YTJf&hD?hI`7q5d=uTk&g8YCJa~&e6@r1P0g*)w3@luZvMdgpvd_5>>G&?R z6Sugc!YQNk4dC8zz<|3U%W0JlFMb=cE6{*i&2kkL?VZql?!h~5FI45VEx1y*wuX83 zX2#)`Sf%dIh-;91`!eGs--8)(&600_W}M`EI3uoA@{J-6T{W<@O1>kA+rJTUF}=b9 z%_s_O{l55?{+>iH-#P9#VEj$|t+(FV(T47+>VG%=izV6@H`GWwfsD9!N;}Q&xK^ES zTSlDD7ed^TVze`$;i-5nOKl@O5&eD--kbTZabAf>brf-=6%)6TapTOF9-CE+ll!QE z0F#fy3;M`b&G#TqSFf7y&sO^{!h4&!ZRkk0dT?NixUocT(#RjF^jDyYbBUbrA%EqHaVns=;N&3U0j%{n+wR-4xUoC!hx>|5-hMI@VMvD&4 zRJn;`TAcXqBiJ5i|4?wF;{ZY@w} zugX_v-#2f}cU~@FDz;%dQam~*Iy+Rz(@#Y+L^Q-5n701q37rtPr?1Kv>?R`jJ&2&ZP zdcG%4mrv&bt-0$|zzOPPIfXhE>QtU~eYo!UidS>gnvOzM3HbBgGhlhnGt`2v95sK{*=oLTj+!%GG&bu<{%CGg zk1_kq`8of*998%b%8$($^+&TqS8kMH z43!Hy@q_l&h*Fo}r~ZSmf>x2PkgkxfJn6m}S!%}mtk5*pb!o1;^wn&&>{ynj9I9WzuRXtuC2FM0}IaKtw& zOU-&L_ec(55MG0^1-?oE!|X&J`jrn{%~oTdQ0nLSy&!O8qfekUq-Dl~W)Ytm2OMUU z0ipF_!rl%RG!_t_nS()Bt{^|H-;AcU|wks$5m|YLQwA{&g|Nbmo2jG1jPg zYaVzjcv$O9@Ua|qUZvr!#ks0@RiP?wDH=E2i#=%8cqvfxD?NDma<2L^nc?9TRe3MK7mufR0^0%D-Aw1O@kYPo>t_l6~M(3 z(DWRPbpi7Fk$3cUrG9|l;*`dN``x!bN3BoHP-{D;t6b#Gtweu{G0!l6iou7ALDR*R zMbY`^VvKyV)$}9T4qsW=oUfXX6{tXKvAW>Ze8|dKkd=ktAw{ZsrcZU^_kPo+``x!O zS8aSXSG@!96|Blr1(o1h(di-ImAUH5WBGt5PvuwUj87lcd~E(jq{VV|uJ1zS!Xz-S zdAkw-qOP-5MYB)c zfZvDhx?JxvZ-D12;CUtRjCm8){Q#T~W%ktO<-T0M%3VKwEIUdLkG82VV9fVMeCpTu z75@}4gWoU2Jn(nqNnB;8Pc3FVU}YZnyStpPI7<}+M+IZ3_u^R^KQ9132SJaCA~mOD zw#sXr1N~vHs_yowR{Ww;FZdAhWyV3@%g8eedXqsb1D`t znWdJzig^v5c-9NK(2GECj+~mU_TAxAU&621)Zu>D{ILN15n~S8b@RvhmS4^BU8Ep^ z9esqfsr8X^weO?&SOb3hSub^z#4>q5gt)_uTRa{5+J!3b*ix1KLYZRx^Z5Nh-~f)1 zHd!3&bn2iUgM1lnVcav{!Bde(p&f;G6yQ*}!NHwp{<1uE)~ZG7EZ^Ca&bh;=Q+O5T z`+Vqs^P&IEUzM-s-&ZoGaWn@wnhhKksdMjh$&k8SRd*~0b00hhG@si6owRa#bUx;1 zzOPjINA;W@K>Z7s&r-`@oeh3A2fTeQbj@Nlx1$6!I1e;}MQn(%@WA z9C*GfkMEti>Ya&MYAeQW7WnwASnhbv82AqE8O|jvfWwDxABg;#F-^_zEl|E3tgqH* zk56j`JkYVugT6K&{Ao7eCT|^IJx%qknWpY~g)mUgLS`XdAzgXWeZ{2LIjZ=+%(-pk zndae~&#Q9P`1x7tb^KDSw`961d3Cxf;GAyFllVU%?Nz49dZ9q^eT@ZJe@-~mN$;%7 zDT8!({k{dcShwV1-GX%rU|vuu>z1hCrB!5tUY7tzdlzS^gZS-XJ8T=WgYVDa_kPp1 z_uXB_hi?hY1^(w^?#yi|9HR!|=y{X^&$F8SsH$O4e3xzen&66jBPmb&s1tX1)C6`>(doUSVm zbwT!m*VuAb`hGA+SryQy@w-dPE6+P<(v!zmlA}t1>k`ygg8E8YW{+t+=BWLZfMaEr zdcoA?e)pY~tIk3{&%zu#t7Y!^>@lrr8(?10lK0(Rm*^L$s}ORo5OZGikBIvjGr?$|HxURB~c&82<-94=&9p$T=NMrAp5>jttFzT= z(2eko%crZ$0befqApC@DgI4r?m8(zCwe~c_W_C5^lC+JnalQMBrmG^%#UjvZQDy$v zLc)%D=4ZKARx)Z;OU!k98O;=|@w$3^R9T_?z zMFFc0rI=%1>ggH zDL6>@b0p9Ak?%96J(h95XVf!ix|)-Kz6D(Rfz#18^u67tanL8yNTZ~O%rt!5!O^hrEabV zp+|Y*efXY6KKMiaeK}f=wM?s6$Tb_rq8MXQn7}%hatrj>oXAq0_+9=g`^<69^~7QA z>&ipeXh7%;AKDJruzHy_ijkR_{fq_GQMA7!aslSM&sqr-@DOx`1AK}G#>u^y&H{( zKY#B=2SKF89RD;M< z7l8|Na8qQb_?VugEPFotFeh!Siq<3m29+U zI$aCbI;S&R;C9stFRnCBn&^4guKv~3M<>mC7;F{;->5cd{8t^{&Fvfq`^F*}hHGSG z=$r)L@JZ9=U5)UA3D(57h>sUMSt5kS?h+i9dxKZ;3``&#@4{Y|ZYS->^ghHi=rb5P zXwoTZO)oatC#)RID0N4=&s%Ut3UI{mp-7GW&FvTz@q&NUhF=K6 z?!o663(uh77F;Ex+R`YBL+)oT8f18I2p(c_UA0mdb1di$D=2&zWgK4N)c$2DW&2p!RP=xi1v(yzr8B9X0qydy}Co9)OL4d#cBCE^Ti z5m5DGmW3B!kpGb#fl<5-wG(>ruQQN8coMg}B|v3{VBlr>rOIjv8EN#niO+yIpLH=4?Wu^1aPWP#yubD?} z*tI5SlyogV`B z;g(1zQU=l~IFt#`UKc)U;#*rctXAp)R~+Y!O(D;rEGDJQ=m&^>@?=f~^%7G!N#r$| z#uSFv2oSY~8084H@Lp{A2BaYY);Ry{nf@_KEbw;7V7OiXgTYfRJEA^ew_Ae~Y)E}O z>2VkQi_MJR>4Lp3(vE4O)U`r`T7D~a1!{0`PBAYcgEy7I6mEJbB&Gfu=^0wFXSfjvbB#B!xP;e(HogSFuOJ8c)299=xo801dUlTtF!mVSl!nBlD77^m z$KIKV8E30t4?U3qGX~>m)69=ZCp0{InTOJ4LBm@5twc#Zb|UV@oxG;6gIbch*@au1 z`NY$8$SfCkcD2Ibf*sUz_g`FPTXASst`<}OMyR0ufc!+~O1NulghO%EWEg9tw7Cy~kWbkyw*!ebbuA6*fh$Go+ zT6#%%DFHLA6rQWiyD-0@J@6`Xeb!`|sb|YB+&pC{iKrIR!575bNj{iZpYzZe~oVxJmT%(z$6QyooFIio%5qCEvVb>dU!A~06lztZh zcw73N&f97&;bjE^)RRbcbQE)t=bh;iV7t^t;Bz%8JT~1KTN%Yi)qx|k5RU_&Nzh|88maXpB_u=MBc>Vg3a!q$EffL+Y z`(SE>X7CgL);?TY-+{}q9mci+9}u7x@fknHXUgQtX@Ieo%6DI)S$|DI9rU+GV)DJ3 zh#iGKH^j|Le{4fUzLD6h4`Zlk_SMNqY*({B(#vmS*77zcG`{lW+8a95Wv*DQm?Ki< zW&sjS#I3kBuqKWUMEImu`RcTmq%${mx5aRuIR`YZ?#&{1;l~tijclPf3P84~eSo$u z(w5wgqenKBSJk&{s&8Cbsd1izlNz-_p0&U&i0wg*JYZ`H;^PT@ceorb#etA`BG$jl z+zE9BPCN9*dBe~(wJlpWwKg=>U%IM7*ZFqbSO;Lx@m_UV`Z*ZEiWa9PyLiI@5`!G{ zQl1FpbzT^A967~FiJiQM3RmN;)FpM7?4(HFE#0`+S$|$@RYne|+_+gXXl`a-q;Nk2 zFJ6rVGZN;ZJ?4W)ShRaZZ=5#j745Oa3Y;(JC5gZO7|w4U#LVPc~4fgi2-82o{4+dl32+#gZm*)9+A%6RvmoIkSgr|)FJb+ceo zN!+r6^5s4;kS1>$l*@r|{tCyoAp3avCNAvfkrbYy=E@Gx%B_c* z6FIFpRd?HW5VFqz%E_UR$?2=c!}gMipTXdFCw8Jq>-3jg*!K@@mqWWfxP8bRZ^qGE z*PTbT0NLEqq)&tC`+Et|Mf%#(6=oEo;qDl|HWDe{UcS}}U0=4ev%g;sa^p%=J}<>h zH)TuPaQ6=nFd_2#rEN?K^S{{A8<*V}ayobskhff44=F?Au9xduSB?7h6m{9730?P} z^!XL+w921l!fX@%v4Maaz*QbNTM69D4VS$0Tc3m5X)c;Y7w1T%vkwQ~pFQchsMP){{XP|5_C2cc ziJe>dyUT>$dAr}_v+>^S$v0}!$36ML{N&GDpNT$g;E^oX+N`lX$2=20pv_V() zAOqBV&m($1RdnkR9vJes*Tf(Fs*c}(vkvWfF>catF!N`$N2l9-t;@ul>ZS}_{rmHM zXO=bfeP`E#^!j2v6!H1xOKWIi$0$*s0+B$e8yMC%Fn$qr{Dmu5h=vzOJk{%t>EZ4`KG~I% znDAVMLTZb&OL*K{lc(K$6bg{elTt95$otv+2XO*bK2zsR=umnJtg@MS%(LP;I& zG2t5?etD0{x6jPOag(p;Yr33WWrcYU-I5t!?a627KV2v=!?=j6+bmq!66+u6#zKM@ zg?92n(TXg>D?OI&xIhs0c zoyNYgWU0BsOO}_sp$%&~-o1fK{2aWdtCFW{s5pT@FlJD}s7i@qMP4L}62q~H5cH6l z&(%rCi-G|X{R2S_eyDV0jl%{<%B+*OXc-N7Sw_qj^)sr-7`Ur23`YB)lVZw zP{$oEEQrOhBpIZAz1Ed$I|b^U{rG$k_Cj^1^c6IgTwE&I-6)X=p*?n!D6v1V1rikU zfS#GY^F{a#Pl?NN+;>%<=%jGoWnVA6s=(F2Y zp6)LRdnAuNxA%V=y7>S@+be0^6wa)OoeXDOB(wo2vmZQR#r$lYe~u3KFVvwY zn;PGeSzm=W!(05m?X$Z5<`X`FH_OxBz+dU~qF*RUx9t<2Y^v*XllRZgSMe!bj}@G} z9m~M6|A&*O+x2WaO*_qhrQsO;+e~;qW7;2mS@*-+PxWaH-&ot^?T_BC)A!cu@-}sh z&eQFf`=TbMqVIjCf2DRuOc;Gdx95reA9%HU@ITPh88lJ!7U5xhpP}Dbnd3UXK#$vz zPw4cDzn+}FZMxk%J+r*iB{M&)pJbNbU!?1wk{&*%+x7B~>R10n^x)xl6~Fou!C?@) z|G(av_NN+;BW8YD&cN!2=+EC8I6Tdq{OTExqF?-p;4qMlzeV%&=x5CQ+^hR%^W`GL zSKs)Qo=2g-*P$0trH0>o`t*;*~(fOwu?=GW{ zc*om%i{!8k@06iuzW=Gmd*556582~6m3)|LyaIo#`SUgp0>>xb8oKl}bMmWayvEe2 z{YXx(;J-H}^cLa49xpF{-u8d=cpUk9=Df8Q>Unqg<2rrM`!m-G-d@}F?>Btgp67Nx zo4PMR+JO{C@v$GU>)1 zhMte=Mpgs)uFuYA zJ)qyaJbL*3f354^d$z9M*6X9indNPIk4~YVl>W8OU-9Y8a`&70Huluyc)7>)ulXM{ z(~Hi}tVfx7R_3YS?%!1NWt-XGy~oaI!m+sSwPII2C66!qwQ)>#@a zN9O8q@3|g4dCL7yzy5#ieQlH@S9#{`>Bbg#Ai@|Bjz5ZIU<8bf;+@z6Y$LGQBZyf< zVuKDgAmcBY%!gpcMviAm5r$ZVfrzXD;W$Zkx4Ko`t?m}dWRG$(8_UaVtgvRIWev!9 zNGc8nfsHA{7%Qyf>~rfrcc5$Ljea>!&c^4we%`5m``-J0J@;01w+f%*67f@#&-DtP zSzpHAxX#*wv8&&+vF_}8>pUO1H=nrfkM%|Dc~I{8W}YPPSL^#Wj_)ykA^TCid1KvG z9P|BBJ=yhHta5+1|F$@!{|)BJUXSCDyn&Z)Z+Nboam+drbIg0;#Bs3WiR%^4i{Uf% zoFZ2L&-8h*@-)Sv$M-1*ui98&HeY2v=T;AF%)9-%<=Y|m1$(_uzO1jE`1^A9`SGlhmiGBI(K815Ul*RH zI8@kw?pYiAuf%h7mHV*!Zj*<2pLO{2rNZMU?nBGxWj^=o$Ijttp2It*n(^&9Jjb6; z$k?4K*o}D~CE4NAHlyzx^SO2Lt7g2PkBw*7m*?}% z?Ef-$__XJZ|Jn7?j~V(qv(ZW^+BJCpoB2yK9zMN$Hdf+eFdY{Hio% zq8AJO?3i?9%=i`AA5vUOm)Vuy$WG^FB+k%Q3%x&)C_&D?Db-@yhf=va{>! zdB)#I9x&sbd~6^p952Uu$sRFwQhp13zE${ZWA~BRc*p9Vb+DIy*uQ%`X3lx@%-dz( zFyqDJa?B5|@4)cHe%N`Ftmgsk@OFX?|5-al-VOi4j2E}FdCSt@fc+uWONaSQv)`n= zh2)n8;}WlXyS{|w1NQkT8@#|j7(a(`aRoaYzai@?N4}Eypi3Taa6gjzEk`~G|EGzc z#6ybX<+wg+|0vFyI;~IO=M3xKx!=qy^;?~Jt9;qmZIR-~I%qI&FA?k-jB|!{D%lkn zm+sfhye|^Q>)N^^A4vN`+B0z(bA9-9{Eh#y4iw{}IB#;J)v^ak{dS&USLM7tJ|}jLvon=nYZ<1Y+;{~jHiH9n*JH$Sk7X0uTXUWd`(P3PQtOIF% zJ=^Exzl1Pvjq`?rot?MKdGoAOiPzG!EAV{!N|W}V&dz_ASO@++CLeJ=wRKSBc#@r6 zUz&N#lK;;7>5N8Wzxm|xF8lX|f?baLU_c&{c(+78@VQUN_d)ANpZiRad?4k+r@sx> zpTrvp#!s@dap}^J3eUygJ)LOyfn|d51cjNnI^^(WcceAIZZ8*pC9-})@~H|`5k|8}^(A-+1c^B%$vjg_jI97$Lymnd0gUMk9kuZ?@VF5 z4E@NEU(OZm28>_8{*}g4%v*=|jb{ksdFFAKJMdv6$k60T$qg|QjrjvwuUC+e%TJ8&RJFZR*7?%v6 zt4Q&480Ri|Tsm*m8NbcstN6ZU_qV>?7uc8adbaDUal9JuSAQYqueA$U_iffo++RCy zmHv*|=UHLAH1k&F`ZmYx?08xFafm!QE!ZU|*x5R0aDCo{bBV|PaJW9{{NgY!lAWEm zM&7M(Ug`e4$NEb$&eHvFgY{CMU{_!tCCGo$cr~6oUGCG;dAv`5tIY2!V)?N3QfGd1 zQ}dTx;=KbLr4E1lcR%v*lK^Cp*e-{JYn#=(Zi z{yR@UF6DW5lQke(yBz&EFu^Y1cuo2tjhEnf_fD{Du#b)i{btuU%?WmiIkUdaVw{a9L&oKR z5I@U*Y1V0hbs+I>KtH?*`$v_1DcM=R>d@Z`_d$uDJ^GPhpG*7dkn`4=-#8E1{MLBR z$#Y+o_RAXM9FRApK2P#|-{-zB@%V^#*G`CYp7rN&KbPVXaD7R}|e$8#h+u^@har!Z*e^7ypdr4CYcZM+{w6%xF5yiXY0V> z`trih^Q>Ki=a=m~?@Ik~?C+9}m~*@2hyA_Z1bIUm&nHig*}rjr?fUA>M~~x4`EY4h zBX3A?sk08s+^41f$dC^tJDXpJeVOF`COxN4vJR@Wll-uMACP39OZPKL_IZ~1jq`?G zUyc5j7(c1cEA-<+=0nO`K)!l}d=Te*+m|EurOP^vug}^Aw(iMSl3j)M+~xDhcz*48 z_V&as(;U|)+1YthjB}m)*0Y89Wyu>w)>T5Vt8-tF?CiWg>#xWCLwXM4ay)m! zzB*=pFXeMMsh%rsbKclKq3#RhgO0!(){h?NEluEq6vs>Q{wThG*!ml?UJ@KnigSZ? zAlcdV4Os_y_DB5rq~+ZL^O2fxU)$llqX|FPsL+q?!nw}+8?dhO>`SSCU5>Yx`H<{V z%N1JO|0M&jX%2*7D$Xm_ z!C-=&9WP{`Cnh}S8j*)w=FJiO$g=Jg_vy0*y9Vv<#K%v*B3tz+3`G%HzME1?~klqgYhe~KaRIE0dTm_Tr2G7cDyS0)jap< z%|iV0EyJfn<}Ds)JKm7}>u^7p>=Hbe`mv!cIa?!WQ6vg@mI z-XhO`uZsC=&xv*VTW9@k73>`5ZNNH^`drbEI`a|lU%S2p#|wnIKW4|e8cf(PyX2QF z^Ba$gjbDcSn_{2G>&n^{m|w}xuCK@as6jrEo?j)ouS#}yyb{+}=KW>-d~erRX5P|_ zi*)~6=lV+A2jls$;{~*vAs?I^s{?D-ryt&g`{^O=GThHk62{B(d~lF;FU=dUUL-pk zzaryT5`I6&`jOZtv?-Zd<#~klc){DdkS=MQm&xfRa)nS}-ogOZ)CzrJVA8!q`uieJF> z1>}vm-4yd!X5KF2cr#Ld8J9BmkN9&!J6?x%+UEWt)qRiSNp{v>kA0qGKBWFgGkz8J zo3yWXI9`JN_VSp&){idj%B*MU=YBoLufVuS{Nge$Mb@dbz8>?IW`9WM$q{)i$$FN4 z4`58YL*(5}F@G)ZI?Tr-w3F%}#r4(6LsEY8tb57M<~PSa_a~hHe4Y=sP3m9r)tL1c z=c{A+<^ERTyz%p-U0;^Gq4>N>vU6E4SFw*y65?E99rSokl7^E>z}^L*$A8!-A~|5;_;dh|CQXIocQ)6V7#A+C9R0mUuE`KGN(rsSXs+Ya#b(i4VHAUdS6#f8?3p z9{rH)66B2{=au%OJpFCZ4{3c>_R$X3^T|Tp*EnyTcGA2a`+Pj%=TUveIplc9*UMD2 z5{EpLnQ%@VGtS$1u9JATKt8BV_`QM-{TK-67h8XM*6G0s@k=ouJ9vNeEFsPn`rDjv zf9Y{w81nog)ys(MlkBV?BgQYox;jNzUzL93xju>i6!V+peac&6g}8+0T=|mv+-aocrX{F5@iuTVR~ajLYj{<5@nalMk8`&bwpw z#}?K>ysm8gM%=efn^4aK@=K0!mi9r9aqf{PrG2Z;`cpi2O7&b|zg6h3#0L%9)yel# zehZdQdESutdBE`!6MmjDCXb)NbF37XJo~aw9+K{V^IV@~XY-a}oGYAH8m~hh?~`Ao z`{{)Bcfxt2#PxM2{Juqn`8~k?ka(!Zy2>yvQhyZLM+aF~Qk+A^xz6>)@1rcQW!UGE zosF}@{%CXFcpusEDy##^&W=~L{!Vz_StS1j%x}Cu?7SZH=J6aR*%dkOljH*_eiicg ze)gqgmtq|x`13rekH(C%GvR(AOMeGEM?5#if7aiS`H<{voa?NY?K}@j=gBhtZE#aWgyrca)f;@qR%0oIGO?~mA*0ryKOel?DlXyfPm^-|_}O85un>)v4F*OQL3E`+L}y@9g*GK5yo&y!FK2XYD%dBm4WR_PRwozWujdPvQO( zf8L<=k@O&%d)gYkAcE{;vK0O4EG5TiZB)>1-2E`*SI4Uz%n7 zU%1h}@-ky@*K2>CYJZ>Eet(Yhbw0N7`v<3*@3)^f?Y!s2{@C&D^K3h=Mf-L8^Kg6J z;&J{keuLc`=j&`S>j~&@@Y;>*bxt>5PydmLM=AEcGdo}AbLQ(Rxv?HIeBYW~uYJC3 zzt3mAIqy1gz1`HXmj90brXqj?>OM&6@1~UtyaQ5(uJP=%l-dhjO#kR71Wz9HrETlk6dD|d%%CnD>Z-(KI>iW zgG4?8-~U#n9>H~Rr@G>8O3nN|)&~42#DT8yHb@q_#`E8))Md~${u*Qlbd42=3ti(K zkUDgYXX8T)J?Q8a_0W|{9flqPpLh@A10A3FuJGOl^(1tSH(aOGwr^n^;HM#Z=o+v5 zZKbY)uJKcl{m?bueVbAZ=mGGD5Ffh6OAjb@5W2?qLXJS!_#2QAI^J!fo`mQ)s81q~ z5cSY>gm?e0Qc36<-&{v7p%;KGf|H~^q3*A_<6(u*Gs^2 z@4(uiXMlhE`^XFQ0Qe~6KIj_X=piQ1HC_cte0w^=Ds%_B#@iv=p=*5QEc}Fy_d%-n zLv}!SfsZv&tI*YgQg2wr8ldCd66#}XSOau?Zn}E$7nC{#-2q+=xevO=&vum>LDyLP zGo{pbuzp|_l7g9`MGel)4tz@s2EY6MlfAd)5WsuxZNl9k4Jx zrK+$g0Y84yR5Taf;i)co_EgjhIpFn>1F+HfH_yd5&^12ic~hznJqdha(v0r_*G`>M zLtMvaDXUMv&|LR`3okZ$2l%`AVAK#cc<+h2;7ra1{M*+~sl;~?PvA>0#&zf!;M*aW zLD%^B+on_zy2j@hrqq6I1H1}yJ9Lfvi&M&nuJMbI0d#zJv-;}0%o+mVhu>}d#b-*Z zQ{OWc)iBN%>df~}sQ~tP2e10Z`=-=U=y>0)y6rmnrE3HDIOMeNVGY3ZuAfp{pleh& zPN^((jn9GTZ{9qm z#?bLz4)r7?;*bwvOi1csj0wCSvJJY%({GtlIp{bCsyiXt-UEJopUFGk&!Im5Va$cT z^MHQ>DZpOihdzclL)X}X?1zr?nc7=3F~r$WJ?|5k7j=~c&eRcq*d&2}_^G;>ebDi4W%bU$ z)MN>GE94Pe*Vy|Wa{PVtBk=Db+n{UAKa4m-$NQnx&wU@`LdQFc)x(f7bi5Z-?Rpfk z)7OEg{J>mK0(U|*KjU2(>bnqa69PXF8XFIIKSXmZJ}+Cn|1pjOeAy3;4etBYA3^ju zcn6z$$&ZW;-b<%uA$kpXSFAeksJV{!=c>mc`nr02N_`fh=f!&m)clWW54_?DGbY~a zq#lJtYXjajHa2+QlzPKI7#qBsL45mf9rwxVAxIPx;Ehk3 z>lNT*kZ3*sIHi6EqQ}8|G}W7)GS~6h^Xji4`Z_+3U%ee~k=FKjhne~wBw8ErezhsO zj(4l6JyV;an7F_%Oq=UH;NP6LN$u0?1b%A!CNmfCn^|KM0(ZS;liClP2w%5J)uHbP z&ODw?N+lUE?PqS?C&DkUVsa zcSDNM2fzzoYR1n2U-k>w55b=q;K{!@9j!kJENp=d?CZe85Er_}FGCJM*ZBOGAx0Fyu+-1K_uRd0K4_(SyKS z&Nu6HfeR4bgBrgL*#aAluebnyLD%>z)HS}3y2eA0%V5(3Zp)f+GQgdXt8iW8-H>ac zYaBqT&^5m3HOMD)jTbu@f37&`E`E}B+DT(1Ma1UU*_ z<2x=!-#=#X_o1H#UE>;cjfbgg{0<}yn-KWYH^5)$8Q=qNH1P?5FTMmm;=0DqLWoo2`j7<;tg8yW$JHXFD^q3y-2fQ8vZ+IK$ z0^SADr3+8$bcr!#_cY)t|JAA{MHNN~;ksIh5vyc(=9PnmHWDl(W8u|#=HQo1^C8y7`*_z38L5R0>1=_e0(SR52DYIA#ko}`mqCi(Yx5! zz*`{^mtHxoJ_5;LE{&gnTnJs`=qj8qpldws-H11IjpspJ=sDmQAh$#B0q=v{30>m@ zkS27EueciLcjy`~fdtSsz84Zg@4XNHUt@gH_&e7kS3ffNd(h8-uJI2bS?C^c>IQHo z^dxW}MEl|be+0Q4*EQZ+My)~D*n;eZ-T`jC(b!~w|MY%v3$CkQpH}aIG@xsI5aL7E zxM>Ia8F~`<1&EIG0Qi!fW*m)ILGFc(#!Gj>N9YCM9gq;Z#?{@J=cvKO4}deFcYx=A z5b=kOchjk_LG+#;0KdA&_=R`psY~~odGWqCbv@)l*lT>jP52sgjjxB4p=-PnvJbio z{5y!QlMwj!n~h!q-Vf1n3xJ&und=%Kqpqr$=N9ZEdK_T-H;j$OH$yyJ*SHUI5V}SW zaxe4%_!K07u5LvvAbJfNuirPVzJ=>$;3E*{af4@m7(POGfbWLrIFx|5>+4vj#_N9* zbp@L;@P0@e`VnBwMU6q%xB}604S_$ReiV4lN6hsM@LK8`Z=t>q*rcxU&!`^)p7C3z z?=)Tp(c^0@QP;Qx(d%pjFZig@v%mr5FxIB=D6eZgbHB040B`*mVgQ?cz%E4RMdMNG zV_@?(>{+ncTthEG^cuDSZ-boiW8@I{$B-oS0q|>(6m*T>hv5bnM{p-TlS9k7k zZock=dv4sl>!Pi{bZ%y=bKS0Mc3*qrt{X1edd21c@to{dXV2cNcU^n+j@`SiyJ+hz z*X`N*`ir0YoC~ksv*)^<@7r;Ug8_E!xoGQ6AKdlYJ=c`4+j;e#b9UZ%%?Eey*?s-q zbFSIF^R-v+*?I2GzqHladG)RvufJ~3-go@$Yq~X?CIV1cEH0K7 z%ZrsocX7BFEUFIr8`tye_+QWH3eVW^clYWHKx#F!nqBR!4p)QK(Q3Fl#(A}wf%Ot-D~&TgLcp!wa0CI zvooXc2uXEjyR*I7;cPHFnpJa&x#V1WE;E;%E6f$=N^{jY%rWQBb>{kWgSp{cI5(b4 z%{%kC`TTr&zA|5*Z_Ib+d-K8kXg-`zG?UF#Gt{@OuzgAjv*J^8xHE*rE)>|8_1#4ihakLml-X&X^CWa7G zuXNybzFlY++og7;U2W^kc92({)giJPBCiS5N@2CQT3vNl>#L1b4|Nl+RuPx+T4BAo zURkfM*Vh~C{(5J+>yF>` zhsd;AN+3F!rNUBisfy@$Oa4+HkqHr(6r!SIQeLhg9*yNL>OfaPVkLh{AE;bgu z#UA=lS8B4AimJ4P8m+bJtxl`k8n%L#@)PXGBKpzwJ@ljQ#?T-8DfFYR;PO&ssgC;9 z)vIeafy&J+XQQfh(XIY+XL+zZM4ze^XC=LoUn#6qR;nuv)NpU5zcN}0SCZ{iJKN5o zj?3*D>R4Ct5X_`j6RT z)8V?Z2kXQ2vCdJ+yconbeH9XJjd3|r>g`^)J3`fLYPKLi(Q zCe%Dw01H;hfqgJw_|Nd4X1@%$Pcxs}tf5yr%|Ub69HVD+zvLGR=#^^JDZPdM!U(;R zTud!y!I34fWDPvoS?ro!0Zf?&m*_sKw%mv_`>jDMY>itf-$57U(M1(7W&>T+Ll=#} zm`QX|7F|?|IL2S0);Zus0>vlIWr=x~LTKu)o$p7Y)%x3SE>2 z2Nxp#X{>wbqCUDP)H$lmC=Y#<^it@e9J;8CE~=x8y6B<+U6eoaGj4`Z2+ztgXQrmKVLx?s8hOqalEA_Jz=yQvGN^TBijFx?nT=YZ+*V7dx+)&`ia z2c{c=>5@1>WO05df$3^sx(=9b2&PlmchX?G0+_A}rt`4d^ucr?m@WmT%Yo_2V7fY( zt_!9Mz;uaLGTM)eI1jmCIv-3o0Mm`ZbPkv<&yz<3OxFX`jlgutr4)K77wyzFFkJ^s zHw4qEtgB~hIyR!$T>x1dS=tSb6hw|v53VNu4eY%Gp8m%PSN%T-Q+Ob_Qoe!oP zfa%6yItNUb2h&xsS2wUv_rP=`FkNyj6`f{EYh|2e>gb^^dMH2-CD20|^iUCdxQib0 zqa8fdOjn;#0a_^qp38yf%HX*=c&-bc3&3-U*(5qB8=Z1o@SG2x8-VA=;5i38mj};P zz;g|p^?Eqzjlgrs`4l=R$1{&P@noYtzZmt1i!RYQ=q~ioB_s5S=CVx0X1Z4@QMc%9 x_+YgjdS)2q#GI2-=$v%aJ0*0F8+DJ)P8a7wouLppO5k*uiuNP8_HX{b{|B 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: List[Type['BaseModel']], 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 .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 .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__', +} + + +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 + + +KT = TypeVar('KT') +VT = TypeVar('VT') +if TYPE_CHECKING: + # Annoying inheriting from `MutableMapping` and `dict` breaks cython, hence this work around + class LimitedDict(dict, MutableMapping[KT, VT]): # type: ignore[type-arg] + def __init__(self, size_limit: int = 1000): + ... + +else: + + class LimitedDict(dict): + """ + Limit the size/length of a dict used for caching to avoid unlimited increase in memory usage. + + Since the dict is ordered, and we always remove elements from the beginning, this is effectively a FIFO cache. + + Annoying inheriting from `MutableMapping` breaks cython. + """ + + def __init__(self, size_limit: int = 1000): + self.size_limit = size_limit + super().__init__() + + def __setitem__(self, __key: Any, __value: Any) -> 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 key in to_remove: + del self[key] + + def __class_getitem__(cls, *args: Any) -> Any: + # to avoid errors with 3.7 + pass diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/validators.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/validators.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..7bc532b3e93328474228bc4baa8ae5c22a9c4a02 GIT binary patch literal 264704 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∾mJoS& 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 WV0}cqIsv~Ho1wbb|NbAf!2baTiuFwZ literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/validators.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/validators.py new file mode 100644 index 00000000..1c19fc92 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/validators.py @@ -0,0 +1,752 @@ +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 . import errors +from .datetime_parse import parse_date, parse_datetime, parse_duration, parse_time +from .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 .utils import almost_equal_floats, lenient_issubclass, sequence_like + +if TYPE_CHECKING: + from typing_extensions import Literal, TypedDict + + from .config import BaseConfig + from .fields import ModelField + from .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() + + +def int_validator(v: Any) -> int: + if isinstance(v, int) and not (v is True or v is False): + return v + + 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: + 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 .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 .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 .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: + raise RuntimeError(f'no validator found for {type_}, see `arbitrary_types_allowed` in Config') diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/version.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/version.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..08a99998755e2e4bd93cfb73d71194a96b6b73d3 GIT binary patch literal 53760 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/version.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/version.py new file mode 100644 index 00000000..2ec0b8d4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/version.py @@ -0,0 +1,38 @@ +__all__ = 'compiled', 'VERSION', 'version_info' + +VERSION = '1.10.1' + +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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/LICENSE new file mode 100644 index 00000000..39372fee --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/LICENSE @@ -0,0 +1,87 @@ +python-dotenv +Copyright (c) 2014, Saurabh Kumar + +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 python-dotenv 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 OWNER 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. + + +django-dotenv-rw +Copyright (c) 2013, Ted Tieken + +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 django-dotenv 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 OWNER 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. + +Original django-dotenv +Copyright (c) 2013, Jacob Kaplan-Moss + +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 django-dotenv 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 OWNER 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/METADATA new file mode 100644 index 00000000..5d16fa86 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/METADATA @@ -0,0 +1,594 @@ +Metadata-Version: 2.1 +Name: python-dotenv +Version: 0.20.0 +Summary: Read key-value pairs from a .env file and set them as environment variables +Home-page: https://github.com/theskumar/python-dotenv +Author: Saurabh Kumar +Author-email: me+github@saurabh-kumar.com +License: BSD-3-Clause +Keywords: environment variables,deployments,settings,env,dotenv,configurations,python +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Topic :: System :: Systems Administration +Classifier: Topic :: Utilities +Classifier: Environment :: Web Environment +Requires-Python: >=3.5 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: cli +Requires-Dist: click (>=5.0) ; extra == 'cli' + +# python-dotenv + +[![Build Status][build_status_badge]][build_status_link] +[![PyPI version][pypi_badge]][pypi_link] + +Python-dotenv reads key-value pairs from a `.env` file and can set them as environment +variables. It helps in the development of applications following the +[12-factor](http://12factor.net/) principles. + +- [Getting Started](#getting-started) +- [Other Use Cases](#other-use-cases) + * [Load configuration without altering the environment](#load-configuration-without-altering-the-environment) + * [Parse configuration as a stream](#parse-configuration-as-a-stream) + * [Load .env files in IPython](#load-env-files-in-ipython) +- [Command-line Interface](#command-line-interface) +- [File format](#file-format) + * [Multiline values](#multiline-values) + * [Variable expansion](#variable-expansion) +- [Related Projects](#related-projects) +- [Acknowledgements](#acknowledgements) + +## Getting Started + +```shell +pip install python-dotenv +``` + +If your application takes its configuration from environment variables, like a 12-factor +application, launching it in development is not very practical because you have to set +those environment variables yourself. + +To help you with that, you can add Python-dotenv to your application to make it load the +configuration from a `.env` file when it is present (e.g. in development) while remaining +configurable via the environment: + +```python +from dotenv import load_dotenv + +load_dotenv() # take environment variables from .env. + +# Code of your application, which uses environment variables (e.g. from `os.environ` or +# `os.getenv`) as if they came from the actual environment. +``` + +By default, `load_dotenv` doesn't override existing environment variables. + +To configure the development environment, add a `.env` in the root directory of your +project: + +``` +. +├── .env +└── foo.py +``` + +The syntax of `.env` files supported by python-dotenv is similar to that of Bash: + +```bash +# Development settings +DOMAIN=example.org +ADMIN_EMAIL=admin@${DOMAIN} +ROOT_URL=${DOMAIN}/app +``` + +If you use variables in values, ensure they are surrounded with `{` and `}`, like +`${DOMAIN}`, as bare variables such as `$DOMAIN` are not expanded. + +You will probably want to add `.env` to your `.gitignore`, especially if it contains +secrets like a password. + +See the section "File format" below for more information about what you can write in a +`.env` file. + +## Other Use Cases + +### Load configuration without altering the environment + +The function `dotenv_values` works more or less the same way as `load_dotenv`, except it +doesn't touch the environment, it just returns a `dict` with the values parsed from the +`.env` file. + +```python +from dotenv import dotenv_values + +config = dotenv_values(".env") # config = {"USER": "foo", "EMAIL": "foo@example.org"} +``` + +This notably enables advanced configuration management: + +```python +import os +from dotenv import dotenv_values + +config = { + **dotenv_values(".env.shared"), # load shared development variables + **dotenv_values(".env.secret"), # load sensitive variables + **os.environ, # override loaded values with environment variables +} +``` + +### Parse configuration as a stream + +`load_dotenv` and `dotenv_values` accept [streams][python_streams] via their `stream` +argument. It is thus possible to load the variables from sources other than the +filesystem (e.g. the network). + +```python +from io import StringIO + +from dotenv import load_dotenv + +config = StringIO("USER=foo\nEMAIL=foo@example.org") +load_dotenv(stream=config) +``` + +### Load .env files in IPython + +You can use dotenv in IPython. By default, it will use `find_dotenv` to search for a +`.env` file: + +```python +%load_ext dotenv +%dotenv +``` + +You can also specify a path: + +```python +%dotenv relative/or/absolute/path/to/.env +``` + +Optional flags: + +- `-o` to override existing variables. +- `-v` for increased verbosity. + +## Command-line Interface + +A CLI interface `dotenv` is also included, which helps you manipulate the `.env` file +without manually opening it. + +```shell +$ pip install "python-dotenv[cli]" +$ dotenv set USER foo +$ dotenv set EMAIL foo@example.org +$ dotenv list +USER=foo +EMAIL=foo@example.org +$ dotenv run -- python foo.py +``` + +Run `dotenv --help` for more information about the options and subcommands. + +## File format + +The format is not formally specified and still improves over time. That being said, +`.env` files should mostly look like Bash files. + +Keys can be unquoted or single-quoted. Values can be unquoted, single- or double-quoted. +Spaces before and after keys, equal signs, and values are ignored. Values can be followed +by a comment. Lines can start with the `export` directive, which has no effect on their +interpretation. + +Allowed escape sequences: + +- in single-quoted values: `\\`, `\'` +- in double-quoted values: `\\`, `\'`, `\"`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v` + +### Multiline values + +It is possible for single- or double-quoted values to span multiple lines. The following +examples are equivalent: + +```bash +FOO="first line +second line" +``` + +```bash +FOO="first line\nsecond line" +``` + +### Variable expansion + +Python-dotenv can interpolate variables using POSIX variable expansion. + +With `load_dotenv(override=True)` or `dotenv_values()`, the value of a variable is the +first of the values defined in the following list: + +- Value of that variable in the `.env` file. +- Value of that variable in the environment. +- Default value, if provided. +- Empty string. + +With `load_dotenv(override=False)`, the value of a variable is the first of the values +defined in the following list: + +- Value of that variable in the environment. +- Value of that variable in the `.env` file. +- Default value, if provided. +- Empty string. + +## Related Projects + +- [Honcho](https://github.com/nickstenning/honcho) - For managing + Procfile-based applications. +- [django-dotenv](https://github.com/jpadilla/django-dotenv) +- [django-environ](https://github.com/joke2k/django-environ) +- [django-environ-2](https://github.com/sergeyklay/django-environ-2) +- [django-configuration](https://github.com/jezdez/django-configurations) +- [dump-env](https://github.com/sobolevn/dump-env) +- [environs](https://github.com/sloria/environs) +- [dynaconf](https://github.com/rochacbruno/dynaconf) + +## Acknowledgements + +This project is currently maintained by [Saurabh Kumar](https://saurabh-kumar.com) and +[Bertrand Bonnefoy-Claudet](https://github.com/bbc2) and would not have been possible +without the support of these [awesome +people](https://github.com/theskumar/python-dotenv/graphs/contributors). + +[build_status_badge]: https://github.com/theskumar/python-dotenv/actions/workflows/test.yml/badge.svg +[build_status_link]: https://github.com/theskumar/python-dotenv/actions/workflows/test.yml +[pypi_badge]: https://badge.fury.io/py/python-dotenv.svg +[pypi_link]: http://badge.fury.io/py/python-dotenv +[python_streams]: https://docs.python.org/3/library/io.html + +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this +project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.20.0] - 2022-03-24 + +### Added + +- Add `encoding` (`Optional[str]`) parameter to `get_key`, `set_key` and `unset_key`. + (#379 by [@bbc2]) + +### Fixed + +- Use dict to specify the `entry_points` parameter of `setuptools.setup` (#376 by + [@mgorny]). +- Don't build universal wheels (#387 by [@bbc2]). + +## [0.19.2] - 2021-11-11 + +### Fixed + +- In `set_key`, add missing newline character before new entry if necessary. (#361 by + [@bbc2]) + +## [0.19.1] - 2021-08-09 + +### Added + +- Add support for Python 3.10. (#359 by [@theskumar]) + +## [0.19.0] - 2021-07-24 + +### Changed + +- Require Python 3.5 or a later version. Python 2 and 3.4 are no longer supported. (#341 + by [@bbc2]). + +### Added + +- The `dotenv_path` argument of `set_key` and `unset_key` now has a type of `Union[str, + os.PathLike]` instead of just `os.PathLike` (#347 by [@bbc2]). +- The `stream` argument of `load_dotenv` and `dotenv_values` can now be a text stream + (`IO[str]`), which includes values like `io.StringIO("foo")` and `open("file.env", + "r")` (#348 by [@bbc2]). + +## [0.18.0] - 2021-06-20 + +### Changed + +- Raise `ValueError` if `quote_mode` isn't one of `always`, `auto` or `never` in + `set_key` (#330 by [@bbc2]). +- When writing a value to a .env file with `set_key` or `dotenv set ` (#330 + by [@bbc2]): + - Use single quotes instead of double quotes. + - Don't strip surrounding quotes. + - In `auto` mode, don't add quotes if the value is only made of alphanumeric characters + (as determined by `string.isalnum`). + +## [0.17.1] - 2021-04-29 + +### Fixed + +- Fixed tests for build environments relying on `PYTHONPATH` (#318 by [@befeleme]). + +## [0.17.0] - 2021-04-02 + +### Changed + +- Make `dotenv get ` only show the value, not `key=value` (#313 by [@bbc2]). + +### Added + +- Add `--override`/`--no-override` option to `dotenv run` (#312 by [@zueve] and [@bbc2]). + +## [0.16.0] - 2021-03-27 + +### Changed + +- The default value of the `encoding` parameter for `load_dotenv` and `dotenv_values` is + now `"utf-8"` instead of `None` (#306 by [@bbc2]). +- Fix resolution order in variable expansion with `override=False` (#287 by [@bbc2]). + +## [0.15.0] - 2020-10-28 + +### Added + +- Add `--export` option to `set` to make it prepend the binding with `export` (#270 by + [@jadutter]). + +### Changed + +- Make `set` command create the `.env` file in the current directory if no `.env` file was + found (#270 by [@jadutter]). + +### Fixed + +- Fix potentially empty expanded value for duplicate key (#260 by [@bbc2]). +- Fix import error on Python 3.5.0 and 3.5.1 (#267 by [@gongqingkui]). +- Fix parsing of unquoted values containing several adjacent space or tab characters + (#277 by [@bbc2], review by [@x-yuri]). + +## [0.14.0] - 2020-07-03 + +### Changed + +- Privilege definition in file over the environment in variable expansion (#256 by + [@elbehery95]). + +### Fixed + +- Improve error message for when file isn't found (#245 by [@snobu]). +- Use HTTPS URL in package meta data (#251 by [@ekohl]). + +## [0.13.0] - 2020-04-16 + +### Added + +- Add support for a Bash-like default value in variable expansion (#248 by [@bbc2]). + +## [0.12.0] - 2020-02-28 + +### Changed + +- Use current working directory to find `.env` when bundled by PyInstaller (#213 by + [@gergelyk]). + +### Fixed + +- Fix escaping of quoted values written by `set_key` (#236 by [@bbc2]). +- Fix `dotenv run` crashing on environment variables without values (#237 by [@yannham]). +- Remove warning when last line is empty (#238 by [@bbc2]). + +## [0.11.0] - 2020-02-07 + +### Added + +- Add `interpolate` argument to `load_dotenv` and `dotenv_values` to disable interpolation + (#232 by [@ulyssessouza]). + +### Changed + +- Use logging instead of warnings (#231 by [@bbc2]). + +### Fixed + +- Fix installation in non-UTF-8 environments (#225 by [@altendky]). +- Fix PyPI classifiers (#228 by [@bbc2]). + +## [0.10.5] - 2020-01-19 + +### Fixed + +- Fix handling of malformed lines and lines without a value (#222 by [@bbc2]): + - Don't print warning when key has no value. + - Reject more malformed lines (e.g. "A: B", "a='b',c"). +- Fix handling of lines with just a comment (#224 by [@bbc2]). + +## [0.10.4] - 2020-01-17 + +### Added + +- Make typing optional (#179 by [@techalchemy]). +- Print a warning on malformed line (#211 by [@bbc2]). +- Support keys without a value (#220 by [@ulyssessouza]). + +## 0.10.3 + +- Improve interactive mode detection ([@andrewsmith])([#183]). +- Refactor parser to fix parsing inconsistencies ([@bbc2])([#170]). + - Interpret escapes as control characters only in double-quoted strings. + - Interpret `#` as start of comment only if preceded by whitespace. + +## 0.10.2 + +- Add type hints and expose them to users ([@qnighy])([#172]) +- `load_dotenv` and `dotenv_values` now accept an `encoding` parameter, defaults to `None` + ([@theskumar])([@earlbread])([#161]) +- Fix `str`/`unicode` inconsistency in Python 2: values are always `str` now. ([@bbc2])([#121]) +- Fix Unicode error in Python 2, introduced in 0.10.0. ([@bbc2])([#176]) + +## 0.10.1 +- Fix parsing of variable without a value ([@asyncee])([@bbc2])([#158]) + +## 0.10.0 + +- Add support for UTF-8 in unquoted values ([@bbc2])([#148]) +- Add support for trailing comments ([@bbc2])([#148]) +- Add backslashes support in values ([@bbc2])([#148]) +- Add support for newlines in values ([@bbc2])([#148]) +- Force environment variables to str with Python2 on Windows ([@greyli]) +- Drop Python 3.3 support ([@greyli]) +- Fix stderr/-out/-in redirection ([@venthur]) + + +## 0.9.0 + +- Add `--version` parameter to cli ([@venthur]) +- Enable loading from current directory ([@cjauvin]) +- Add 'dotenv run' command for calling arbitrary shell script with .env ([@venthur]) + +## 0.8.1 + +- Add tests for docs ([@Flimm]) +- Make 'cli' support optional. Use `pip install python-dotenv[cli]`. ([@theskumar]) + +## 0.8.0 + +- `set_key` and `unset_key` only modified the affected file instead of + parsing and re-writing file, this causes comments and other file + entact as it is. +- Add support for `export` prefix in the line. +- Internal refractoring ([@theskumar]) +- Allow `load_dotenv` and `dotenv_values` to work with `StringIO())` ([@alanjds])([@theskumar])([#78]) + +## 0.7.1 + +- Remove hard dependency on iPython ([@theskumar]) + +## 0.7.0 + +- Add support to override system environment variable via .env. + ([@milonimrod](https://github.com/milonimrod)) + ([\#63](https://github.com/theskumar/python-dotenv/issues/63)) +- Disable ".env not found" warning by default + ([@maxkoryukov](https://github.com/maxkoryukov)) + ([\#57](https://github.com/theskumar/python-dotenv/issues/57)) + +## 0.6.5 + +- Add support for special characters `\`. + ([@pjona](https://github.com/pjona)) + ([\#60](https://github.com/theskumar/python-dotenv/issues/60)) + +## 0.6.4 + +- Fix issue with single quotes ([@Flimm]) + ([\#52](https://github.com/theskumar/python-dotenv/issues/52)) + +## 0.6.3 + +- Handle unicode exception in setup.py + ([\#46](https://github.com/theskumar/python-dotenv/issues/46)) + +## 0.6.2 + +- Fix dotenv list command ([@ticosax](https://github.com/ticosax)) +- Add iPython Support + ([@tillahoffmann](https://github.com/tillahoffmann)) + +## 0.6.0 + +- Drop support for Python 2.6 +- Handle escaped characters and newlines in quoted values. (Thanks + [@iameugenejo](https://github.com/iameugenejo)) +- Remove any spaces around unquoted key/value. (Thanks + [@paulochf](https://github.com/paulochf)) +- Added POSIX variable expansion. (Thanks + [@hugochinchilla](https://github.com/hugochinchilla)) + +## 0.5.1 + +- Fix find\_dotenv - it now start search from the file where this + function is called from. + +## 0.5.0 + +- Add `find_dotenv` method that will try to find a `.env` file. + (Thanks [@isms](https://github.com/isms)) + +## 0.4.0 + +- cli: Added `-q/--quote` option to control the behaviour of quotes + around values in `.env`. (Thanks + [@hugochinchilla](https://github.com/hugochinchilla)). +- Improved test coverage. + +[#78]: https://github.com/theskumar/python-dotenv/issues/78 +[#121]: https://github.com/theskumar/python-dotenv/issues/121 +[#148]: https://github.com/theskumar/python-dotenv/issues/148 +[#158]: https://github.com/theskumar/python-dotenv/issues/158 +[#170]: https://github.com/theskumar/python-dotenv/issues/170 +[#172]: https://github.com/theskumar/python-dotenv/issues/172 +[#176]: https://github.com/theskumar/python-dotenv/issues/176 +[#183]: https://github.com/theskumar/python-dotenv/issues/183 +[#359]: https://github.com/theskumar/python-dotenv/issues/359 + +[@Flimm]: https://github.com/Flimm +[@alanjds]: https://github.com/alanjds +[@altendky]: https://github.com/altendky +[@andrewsmith]: https://github.com/andrewsmith +[@asyncee]: https://github.com/asyncee +[@bbc2]: https://github.com/bbc2 +[@befeleme]: https://github.com/befeleme +[@cjauvin]: https://github.com/cjauvin +[@earlbread]: https://github.com/earlbread +[@ekohl]: https://github.com/ekohl +[@elbehery95]: https://github.com/elbehery95 +[@gergelyk]: https://github.com/gergelyk +[@gongqingkui]: https://github.com/gongqingkui +[@greyli]: https://github.com/greyli +[@jadutter]: https://github.com/jadutter +[@mgorny]: https://github.com/mgorny +[@qnighy]: https://github.com/qnighy +[@snobu]: https://github.com/snobu +[@techalchemy]: https://github.com/techalchemy +[@theskumar]: https://github.com/theskumar +[@ulyssessouza]: https://github.com/ulyssessouza +[@venthur]: https://github.com/venthur +[@x-yuri]: https://github.com/x-yuri +[@yannham]: https://github.com/yannham +[@zueve]: https://github.com/zueve + +[Unreleased]: https://github.com/theskumar/python-dotenv/compare/v0.20.0...HEAD +[0.19.2]: https://github.com/theskumar/python-dotenv/compare/v0.19.2...v0.20.0 +[0.19.2]: https://github.com/theskumar/python-dotenv/compare/v0.19.1...v0.19.2 +[0.19.1]: https://github.com/theskumar/python-dotenv/compare/v0.19.0...v0.19.1 +[0.19.0]: https://github.com/theskumar/python-dotenv/compare/v0.18.0...v0.19.0 +[0.18.0]: https://github.com/theskumar/python-dotenv/compare/v0.17.1...v0.18.0 +[0.17.1]: https://github.com/theskumar/python-dotenv/compare/v0.17.0...v0.17.1 +[0.17.0]: https://github.com/theskumar/python-dotenv/compare/v0.16.0...v0.17.0 +[0.16.0]: https://github.com/theskumar/python-dotenv/compare/v0.15.0...v0.16.0 +[0.15.0]: https://github.com/theskumar/python-dotenv/compare/v0.14.0...v0.15.0 +[0.14.0]: https://github.com/theskumar/python-dotenv/compare/v0.13.0...v0.14.0 +[0.13.0]: https://github.com/theskumar/python-dotenv/compare/v0.12.0...v0.13.0 +[0.12.0]: https://github.com/theskumar/python-dotenv/compare/v0.11.0...v0.12.0 +[0.11.0]: https://github.com/theskumar/python-dotenv/compare/v0.10.5...v0.11.0 +[0.10.5]: https://github.com/theskumar/python-dotenv/compare/v0.10.4...v0.10.5 +[0.10.4]: https://github.com/theskumar/python-dotenv/compare/v0.10.3...v0.10.4 + + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/RECORD new file mode 100644 index 00000000..aac2c1ce --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/RECORD @@ -0,0 +1,23 @@ +../../Scripts/dotenv.exe,sha256=7W38K2jr6dBO5wbTIh9H2nxwLFim-YCd6AANvQhaBgg,106369 +dotenv/__init__.py,sha256=bdAGaaBAOc_Hyqqy8UOVjedJDgUNqMTLlmqcOrMCdC8,1298 +dotenv/__pycache__/__init__.cpython-37.pyc,, +dotenv/__pycache__/cli.cpython-37.pyc,, +dotenv/__pycache__/ipython.cpython-37.pyc,, +dotenv/__pycache__/main.cpython-37.pyc,, +dotenv/__pycache__/parser.cpython-37.pyc,, +dotenv/__pycache__/variables.cpython-37.pyc,, +dotenv/__pycache__/version.cpython-37.pyc,, +dotenv/cli.py,sha256=MfmIEYbhDhANP7CzAkgDJUahjKcY5mOjCbDEnJNvqhI,4777 +dotenv/ipython.py,sha256=avI6aez_RxnBptYgchIquF2TSgKI-GOhY3ppiu3VuWE,1303 +dotenv/main.py,sha256=wBUr-lDnDo7fKAi8oHJLxRlna4wvoGTgJdJNTikrGw0,11692 +dotenv/parser.py,sha256=HMB0VVy_fejMuGZ_Fdigzln_dBE9nsAAaZ7olwoAZSw,5298 +dotenv/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26 +dotenv/variables.py,sha256=HtvYMOOyyogGGZv-YkGzeMOKtovvqqGzh_kIB9xuAto,2404 +dotenv/version.py,sha256=NGIecTe1EEM7UeBjKSJ4vCWuGDWF1ZX4PckW2Eguxps,23 +python_dotenv-0.20.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +python_dotenv-0.20.0.dist-info/LICENSE,sha256=0nIJqz0WJ4Ko-OOHK5s1PEngksmqRnpkUiiDQH2NEDA,4600 +python_dotenv-0.20.0.dist-info/METADATA,sha256=fPA8H1g_zWafVdlx7u-TCw3mFyBDJxZh6JmuOdJDxY0,19376 +python_dotenv-0.20.0.dist-info/RECORD,, +python_dotenv-0.20.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +python_dotenv-0.20.0.dist-info/entry_points.txt,sha256=Ta6e0xl3qUUz_ZZ1D1YAR6SKDHNGBPLcHqfzyXq4TVk,43 +python_dotenv-0.20.0.dist-info/top_level.txt,sha256=eyqUH4SHJNr6ahOYlxIunTr4XinE8Z5ajWLdrK3r0D8,7 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/entry_points.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/entry_points.txt new file mode 100644 index 00000000..deb9ff42 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +dotenv = dotenv.cli:cli + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/top_level.txt new file mode 100644 index 00000000..fe7c01aa --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/python_dotenv-0.20.0.dist-info/top_level.txt @@ -0,0 +1 @@ +dotenv diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE new file mode 100644 index 00000000..51f34429 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE @@ -0,0 +1,3 @@ +This software is made available under the terms of *either* of the +licenses found in LICENSE.APACHE2 or LICENSE.MIT. Contributions to are +made under the terms of *both* these licenses. diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.APACHE2 b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.APACHE2 new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.APACHE2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.MIT b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.MIT new file mode 100644 index 00000000..b8bb9718 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/LICENSE.MIT @@ -0,0 +1,20 @@ +The MIT License (MIT) + +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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/METADATA new file mode 100644 index 00000000..0e60193c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/METADATA @@ -0,0 +1,103 @@ +Metadata-Version: 2.1 +Name: sniffio +Version: 1.2.0 +Summary: Sniff out which async library your code is running under +Home-page: https://github.com/python-trio/sniffio +Author: Nathaniel J. Smith +Author-email: njs@pobox.com +License: MIT -or- Apache License 2.0 +Keywords: async,trio,asyncio +Platform: UNKNOWN +Classifier: License :: OSI Approved :: MIT License +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Framework :: Trio +Classifier: Framework :: AsyncIO +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Intended Audience :: Developers +Classifier: Development Status :: 5 - Production/Stable +Requires-Python: >=3.5 +Requires-Dist: contextvars (>=2.1) ; python_version < '3.7' + +.. image:: https://img.shields.io/badge/chat-join%20now-blue.svg + :target: https://gitter.im/python-trio/general + :alt: Join chatroom + +.. image:: https://img.shields.io/badge/docs-read%20now-blue.svg + :target: https://sniffio.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status + +.. image:: https://img.shields.io/pypi/v/sniffio.svg + :target: https://pypi.org/project/sniffio + :alt: Latest PyPi version + +.. image:: https://img.shields.io/conda/vn/conda-forge/sniffio.svg + :target: https://anaconda.org/conda-forge/sniffio + :alt: Latest conda-forge version + +.. image:: https://travis-ci.org/python-trio/sniffio.svg?branch=master + :target: https://travis-ci.org/python-trio/sniffio + :alt: Automated test status + +.. image:: https://codecov.io/gh/python-trio/sniffio/branch/master/graph/badge.svg + :target: https://codecov.io/gh/python-trio/sniffio + :alt: Test coverage + +================================================================= +sniffio: Sniff out which async library your code is running under +================================================================= + +You're writing a library. You've decided to be ambitious, and support +multiple async I/O packages, like `Trio +`__, and `asyncio +`__, and ... You've +written a bunch of clever code to handle all the differences. But... +how do you know *which* piece of clever code to run? + +This is a tiny package whose only purpose is to let you detect which +async library your code is running under. + +* Documentation: https://sniffio.readthedocs.io + +* Bug tracker and source code: https://github.com/python-trio/sniffio + +* License: MIT or Apache License 2.0, your choice + +* Contributor guide: https://trio.readthedocs.io/en/latest/contributing.html + +* Code of conduct: Contributors are requested to follow our `code of + conduct + `_ + in all project spaces. + +This library is maintained by the Trio project, as a service to the +async Python community as a whole. + + +Quickstart +---------- + +.. code-block:: python3 + + from sniffio import current_async_library + import trio + import asyncio + + async def print_library(): + library = current_async_library() + print("This is:", library) + + # Prints "This is trio" + trio.run(print_library) + + # Prints "This is asyncio" + asyncio.run(print_library()) + +For more details, including how to add support to new async libraries, +`please peruse our fine manual `__. + + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/RECORD new file mode 100644 index 00000000..caf2430a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/RECORD @@ -0,0 +1,19 @@ +sniffio-1.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +sniffio-1.2.0.dist-info/LICENSE,sha256=ZSyHhIjRRWNh4Iw_hgf9e6WYkqFBA9Fczk_5PIW1zIs,185 +sniffio-1.2.0.dist-info/LICENSE.APACHE2,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358 +sniffio-1.2.0.dist-info/LICENSE.MIT,sha256=Pm2uVV65J4f8gtHUg1Vnf0VMf2Wus40_nnK_mj2vA0s,1046 +sniffio-1.2.0.dist-info/METADATA,sha256=1feG2RpWgvrsxlrHGBdQWr2qz_J9T2dNk9gHwBniB4o,3597 +sniffio-1.2.0.dist-info/RECORD,, +sniffio-1.2.0.dist-info/WHEEL,sha256=EVRjI69F5qVjm_YgqcTXPnTAv3BfSUr0WVAHuSP3Xoo,92 +sniffio-1.2.0.dist-info/top_level.txt,sha256=v9UJXGs5CyddCVeAqXkQiWOrpp6Wtx6GeRrPt9-jjHg,8 +sniffio/__init__.py,sha256=OVpJIlvGte9qZSi0tbZNiIF6cxVlNIkQY09sNw80m6Y,292 +sniffio/__pycache__/__init__.cpython-37.pyc,, +sniffio/__pycache__/_impl.cpython-37.pyc,, +sniffio/__pycache__/_version.cpython-37.pyc,, +sniffio/_impl.py,sha256=gtPkeGhus65ffGiTtv1w3qaMrfJI04ubcVMrWMW2_5Q,2721 +sniffio/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +sniffio/_tests/__pycache__/__init__.cpython-37.pyc,, +sniffio/_tests/__pycache__/test_sniffio.cpython-37.pyc,, +sniffio/_tests/test_sniffio.py,sha256=yTv4bRyHH0ay5RpqWtdbzHFD6BV02xlBax61en_-OR8,1648 +sniffio/_version.py,sha256=codhqWKYFbR_gKABvhb2_aWOKwuRo4YQlLcENJOvFkQ,89 +sniffio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/WHEEL new file mode 100644 index 00000000..83ff02e9 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.35.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/top_level.txt new file mode 100644 index 00000000..01c65024 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio-1.2.0.dist-info/top_level.txt @@ -0,0 +1 @@ +sniffio diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/__init__.py new file mode 100644 index 00000000..ddbd53a5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/__init__.py @@ -0,0 +1,14 @@ +"""Top-level package for sniffio.""" + +__all__ = [ + "current_async_library", "AsyncLibraryNotFoundError", + "current_async_library_cvar" +] + +from ._version import __version__ + +from ._impl import ( + current_async_library, + AsyncLibraryNotFoundError, + current_async_library_cvar, +) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_impl.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_impl.py new file mode 100644 index 00000000..240d3a2e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_impl.py @@ -0,0 +1,83 @@ +from contextvars import ContextVar +from typing import Optional +import sys + +current_async_library_cvar = ContextVar( + "current_async_library_cvar", default=None +) # type: ContextVar[Optional[str]] + + +class AsyncLibraryNotFoundError(RuntimeError): + pass + + +def current_async_library() -> str: + """Detect which async library is currently running. + + The following libraries are currently supported: + + ================ =========== ============================ + Library Requires Magic string + ================ =========== ============================ + **Trio** Trio v0.6+ ``"trio"`` + **Curio** - ``"curio"`` + **asyncio** ``"asyncio"`` + **Trio-asyncio** v0.8.2+ ``"trio"`` or ``"asyncio"``, + depending on current mode + ================ =========== ============================ + + Returns: + A string like ``"trio"``. + + Raises: + AsyncLibraryNotFoundError: if called from synchronous context, + or if the current async library was not recognized. + + Examples: + + .. code-block:: python3 + + from sniffio import current_async_library + + async def generic_sleep(seconds): + library = current_async_library() + if library == "trio": + import trio + await trio.sleep(seconds) + elif library == "asyncio": + import asyncio + await asyncio.sleep(seconds) + # ... and so on ... + else: + raise RuntimeError(f"Unsupported library {library!r}") + + """ + value = current_async_library_cvar.get() + if value is not None: + return value + + # Sniff for curio (for now) + if 'curio' in sys.modules: + from curio.meta import curio_running + if curio_running(): + return 'curio' + + # Need to sniff for asyncio + if "asyncio" in sys.modules: + import asyncio + try: + current_task = asyncio.current_task # type: ignore[attr-defined] + except AttributeError: + current_task = asyncio.Task.current_task # type: ignore[attr-defined] + try: + if current_task() is not None: + if (3, 7) <= sys.version_info: + # asyncio has contextvars support, and we're in a task, so + # we can safely cache the sniffed value + current_async_library_cvar.set("asyncio") + return "asyncio" + except RuntimeError: + pass + raise AsyncLibraryNotFoundError( + "unknown async library, or not in async context" + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_tests/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_tests/test_sniffio.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_tests/test_sniffio.py new file mode 100644 index 00000000..a19d13c9 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_tests/test_sniffio.py @@ -0,0 +1,67 @@ +import sys + +import pytest + +from .. import ( + current_async_library, AsyncLibraryNotFoundError, + current_async_library_cvar +) + + +def test_basics(): + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() + + token = current_async_library_cvar.set("generic-lib") + try: + assert current_async_library() == "generic-lib" + finally: + current_async_library_cvar.reset(token) + + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() + + +def test_asyncio(): + import asyncio + + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() + + ran = [] + + async def this_is_asyncio(): + assert current_async_library() == "asyncio" + # Call it a second time to exercise the caching logic + assert current_async_library() == "asyncio" + ran.append(True) + + loop = asyncio.get_event_loop() + loop.run_until_complete(this_is_asyncio()) + assert ran == [True] + loop.close() + + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() + + +@pytest.mark.skipif(sys.version_info < (3, 6), reason='Curio requires 3.6+') +def test_curio(): + import curio + + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() + + ran = [] + + async def this_is_curio(): + assert current_async_library() == "curio" + # Call it a second time to exercise the caching logic + assert current_async_library() == "curio" + ran.append(True) + + curio.run(this_is_curio) + assert ran == [True] + + with pytest.raises(AsyncLibraryNotFoundError): + current_async_library() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_version.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_version.py new file mode 100644 index 00000000..7c4b1198 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/_version.py @@ -0,0 +1,3 @@ +# This file is imported from __init__.py and exec'd from setup.py + +__version__ = "1.2.0" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/sniffio/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/LICENSE.md b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/LICENSE.md new file mode 100644 index 00000000..d16a60ec --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/LICENSE.md @@ -0,0 +1,27 @@ +Copyright © 2018, [Encode OSS Ltd](https://www.encode.io/). +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 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/METADATA new file mode 100644 index 00000000..acf7f65f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/METADATA @@ -0,0 +1,179 @@ +Metadata-Version: 2.1 +Name: starlette +Version: 0.19.1 +Summary: The little ASGI library that shines. +Home-page: https://github.com/encode/starlette +Author: Tom Christie +Author-email: tom@tomchristie.com +License: BSD +Platform: UNKNOWN +Classifier: Development Status :: 3 - Alpha +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Framework :: AnyIO +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Requires-Python: >=3.6 +Description-Content-Type: text/markdown +Requires-Dist: anyio (<5,>=3.4.0) +Requires-Dist: typing-extensions (>=3.10.0) ; python_version < "3.10" +Requires-Dist: contextlib2 (>=21.6.0) ; python_version < "3.7" +Provides-Extra: full +Requires-Dist: itsdangerous ; extra == 'full' +Requires-Dist: jinja2 ; extra == 'full' +Requires-Dist: python-multipart ; extra == 'full' +Requires-Dist: pyyaml ; extra == 'full' +Requires-Dist: requests ; extra == 'full' + +

      + starlette +

      +

      + ✨ The little ASGI framework that shines. ✨ +

      +

      + + Build Status + + + Package version + +

      + +--- + +**Documentation**: [https://www.starlette.io/](https://www.starlette.io/) + +--- + +# Starlette + +Starlette is a lightweight [ASGI][asgi] framework/toolkit, +which is ideal for building async web services in Python. + +It is production-ready, and gives you the following: + +* A lightweight, low-complexity HTTP web framework. +* WebSocket support. +* In-process background tasks. +* Startup and shutdown events. +* Test client built on `requests`. +* CORS, GZip, Static Files, Streaming responses. +* Session and Cookie support. +* 100% test coverage. +* 100% type annotated codebase. +* Few hard dependencies. +* Compatible with `asyncio` and `trio` backends. +* Great overall performance [against independant benchmarks][techempower]. + +## Requirements + +Python 3.6+ + +## Installation + +```shell +$ pip3 install starlette +``` + +You'll also want to install an ASGI server, such as [uvicorn](http://www.uvicorn.org/), [daphne](https://github.com/django/daphne/), or [hypercorn](https://pgjones.gitlab.io/hypercorn/). + +```shell +$ pip3 install uvicorn +``` + +## Example + +**example.py**: + +```python +from starlette.applications import Starlette +from starlette.responses import JSONResponse +from starlette.routing import Route + + +async def homepage(request): + return JSONResponse({'hello': 'world'}) + +routes = [ + Route("/", endpoint=homepage) +] + +app = Starlette(debug=True, routes=routes) +``` + +Then run the application using Uvicorn: + +```shell +$ uvicorn example:app +``` + +For a more complete example, see [encode/starlette-example](https://github.com/encode/starlette-example). + +## Dependencies + +Starlette only requires `anyio`, and the following are optional: + +* [`requests`][requests] - Required if you want to use the `TestClient`. +* [`jinja2`][jinja2] - Required if you want to use `Jinja2Templates`. +* [`python-multipart`][python-multipart] - Required if you want to support form parsing, with `request.form()`. +* [`itsdangerous`][itsdangerous] - Required for `SessionMiddleware` support. +* [`pyyaml`][pyyaml] - Required for `SchemaGenerator` support. + +You can install all of these with `pip3 install starlette[full]`. + +## Framework or Toolkit + +Starlette is designed to be used either as a complete framework, or as +an ASGI toolkit. You can use any of its components independently. + +```python +from starlette.responses import PlainTextResponse + + +async def app(scope, receive, send): + assert scope['type'] == 'http' + response = PlainTextResponse('Hello, world!') + await response(scope, receive, send) +``` + +Run the `app` application in `example.py`: + +```shell +$ uvicorn example:app +INFO: Started server process [11509] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +Run uvicorn with `--reload` to enable auto-reloading on code changes. + +## Modularity + +The modularity that Starlette is designed on promotes building re-usable +components that can be shared between any ASGI framework. This should enable +an ecosystem of shared middleware and mountable applications. + +The clean API separation also means it's easier to understand each component +in isolation. + +--- + +

      Starlette is BSD licensed code.
      Designed & crafted with care.

      — ⭐️ —

      + +[asgi]: https://asgi.readthedocs.io/en/latest/ +[requests]: http://docs.python-requests.org/en/master/ +[jinja2]: http://jinja.pocoo.org/ +[python-multipart]: https://andrew-d.github.io/python-multipart/ +[itsdangerous]: https://pythonhosted.org/itsdangerous/ +[sqlalchemy]: https://www.sqlalchemy.org +[pyyaml]: https://pyyaml.org/wiki/PyYAMLDocumentation +[techempower]: https://www.techempower.com/benchmarks/#hw=ph&test=fortune&l=zijzen-sf + + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/RECORD new file mode 100644 index 00000000..0b36f8d6 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/RECORD @@ -0,0 +1,73 @@ +starlette-0.19.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +starlette-0.19.1.dist-info/LICENSE.md,sha256=3LlWd6AiQCQxh-lk-UGEfRmxeCHPmeWvrmhPqzKMGb8,1518 +starlette-0.19.1.dist-info/METADATA,sha256=LPIAI5r0i7IIFTq8td5P9EN1RqMM7EvM5CUSwxvaMS0,5607 +starlette-0.19.1.dist-info/RECORD,, +starlette-0.19.1.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +starlette-0.19.1.dist-info/top_level.txt,sha256=eWSxNxwzxXl9k09QFS8z1V7D3gCryfl1rTObkPBMRJI,10 +starlette/__init__.py,sha256=ACwqBctK6p_9Oj2rXWiSmVOPJURrCCh7l_Ak1Mk2h-o,23 +starlette/__pycache__/__init__.cpython-37.pyc,, +starlette/__pycache__/_compat.cpython-37.pyc,, +starlette/__pycache__/_pep562.cpython-37.pyc,, +starlette/__pycache__/applications.cpython-37.pyc,, +starlette/__pycache__/authentication.cpython-37.pyc,, +starlette/__pycache__/background.cpython-37.pyc,, +starlette/__pycache__/concurrency.cpython-37.pyc,, +starlette/__pycache__/config.cpython-37.pyc,, +starlette/__pycache__/convertors.cpython-37.pyc,, +starlette/__pycache__/datastructures.cpython-37.pyc,, +starlette/__pycache__/endpoints.cpython-37.pyc,, +starlette/__pycache__/exceptions.cpython-37.pyc,, +starlette/__pycache__/formparsers.cpython-37.pyc,, +starlette/__pycache__/requests.cpython-37.pyc,, +starlette/__pycache__/responses.cpython-37.pyc,, +starlette/__pycache__/routing.cpython-37.pyc,, +starlette/__pycache__/schemas.cpython-37.pyc,, +starlette/__pycache__/staticfiles.cpython-37.pyc,, +starlette/__pycache__/status.cpython-37.pyc,, +starlette/__pycache__/templating.cpython-37.pyc,, +starlette/__pycache__/testclient.cpython-37.pyc,, +starlette/__pycache__/types.cpython-37.pyc,, +starlette/__pycache__/websockets.cpython-37.pyc,, +starlette/_compat.py,sha256=yqCApnDFpPoAiMrEF5CnOiTngAb6_pPTR2ykPtxWCb4,1149 +starlette/_pep562.py,sha256=etty8LQhAsUcbZ6r2ZlSpyUqG20_agArEz1gGiByZgY,2779 +starlette/applications.py,sha256=qYmvarqXgwLa_juii4pWoYLWi0kvwWVNzwfh7ds5ons,9925 +starlette/authentication.py,sha256=nP0IcnJNNIB04QOJ5K66TsaTIRhOD3OMzJWVgQGp2hQ,5090 +starlette/background.py,sha256=i_spMdhZWNA4Q5EMEYnTC4qVwlbH2A7LhkJr1EG0BKU,1237 +starlette/concurrency.py,sha256=IIxlJASchhv7T1ik_WQRuN-6Pd0r--_x4gqt9odO0Yc,1741 +starlette/config.py,sha256=wD1dp9XuNn8ypUrSwREOTsY1ZMV-OU5my9xczmRxltM,4488 +starlette/convertors.py,sha256=G5OFkuGVGkaoJDLrrrMjqbmFtsvybzJ0VpLsC-0xH5I,2166 +starlette/datastructures.py,sha256=G1Giw0Ozb_Yib7f3HimmuRtAN7T9UYN1H9mvjiWImTo,22178 +starlette/endpoints.py,sha256=tpOo3BfcMNQC-SoHNPS7BSWCG5u2NZZTtvAF3YWB5so,5123 +starlette/exceptions.py,sha256=wWC8ik8U0cucaOEkK6a9bxgEa_L0r3YFAEvjNdr3IPw,3909 +starlette/formparsers.py,sha256=JqrbOqbOhHvR4K-I1wKV2qUzbbFPSIm43dTVRDmo2UI,8747 +starlette/middleware/__init__.py,sha256=tEegvh1lBhUfHaJ0p-T_9FU7PRT1WHoIc2vZX0pUlm8,546 +starlette/middleware/__pycache__/__init__.cpython-37.pyc,, +starlette/middleware/__pycache__/authentication.cpython-37.pyc,, +starlette/middleware/__pycache__/base.cpython-37.pyc,, +starlette/middleware/__pycache__/cors.cpython-37.pyc,, +starlette/middleware/__pycache__/errors.cpython-37.pyc,, +starlette/middleware/__pycache__/gzip.cpython-37.pyc,, +starlette/middleware/__pycache__/httpsredirect.cpython-37.pyc,, +starlette/middleware/__pycache__/sessions.cpython-37.pyc,, +starlette/middleware/__pycache__/trustedhost.cpython-37.pyc,, +starlette/middleware/__pycache__/wsgi.cpython-37.pyc,, +starlette/middleware/authentication.py,sha256=rP3t8t7HoO3xW8LH48Yo_GY8jzyx7WCrT88m_1O_kJ4,1787 +starlette/middleware/base.py,sha256=uG_c8TgZ23oSXQt1-DIHzonZLbzjeBUQc5CfL1DjtyM,2661 +starlette/middleware/cors.py,sha256=x_pPPhDxTKZq4Zue3dMjzvSI580e_QZG6xqP9OgJ4iM,7076 +starlette/middleware/errors.py,sha256=9BErqdMUSzRPF6aKIL3sK5EHQIVA31B5X6N6C9P76vc,7771 +starlette/middleware/gzip.py,sha256=GJlMYl-GHhkDIPIRchvbat3Fi-DRMITt8zHN6pq2OlQ,4087 +starlette/middleware/httpsredirect.py,sha256=SNTleaYALGoITV7xwbic4gB6VYdM8Ylea_ykciUz31g,848 +starlette/middleware/sessions.py,sha256=h0yeRBo5QZ2LV30p4jvgkbLYO3HNNkWNESeCncSY7L4,3421 +starlette/middleware/trustedhost.py,sha256=5oTnnGRXQC4KJTROs802G9tJzBij2zI9ze11aEdbins,2207 +starlette/middleware/wsgi.py,sha256=YbjlcETXYzaN5--Rk2uC2vEvxAiKwuvWQ7IuOFjU3H4,4906 +starlette/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +starlette/requests.py,sha256=A3ofuUDW_pdc_E5Ui0RC4m7QbTt86MlFLSBylrcG22Y,9578 +starlette/responses.py,sha256=DCESKs_eNeu_PvixQ42H6dhcQ6J-AfhsS44VwaC7wko,12392 +starlette/routing.py,sha256=lN4-tveWiCN4NW3F3kn6GTx29GEE35wPeYYZRPowb-k,30160 +starlette/schemas.py,sha256=K9bDGPCMN-ikPS9hTtl2Bp30LH-O0P_dSGOmS-oDNTA,4474 +starlette/staticfiles.py,sha256=vJM-osz1YCAtml40WIdq96pJv3TLpFL5Xa6-le4DLUA,8499 +starlette/status.py,sha256=qMYRRGo51Lgy_QVnCsG65wDl-yJcIHNusxTzR0cdDQQ,6223 +starlette/templating.py,sha256=dwKMdegSRx-r3MUnDWHiXmz2GI_3sC02EATBJinyqbk,3620 +starlette/testclient.py,sha256=FVT6gx5yJ6E4FgMbFO-7Gf3RZ-6Fu7zW1p9ZU18IyDQ,19673 +starlette/types.py,sha256=RbisZ8DEsquztH1HwK6_8Iy5ZvQwddYcDDFW32KEN3o,302 +starlette/websockets.py,sha256=dCDRvGsp62FXrxDv320P7fv5QggUK21kneokFq9juWQ,7317 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/top_level.txt new file mode 100644 index 00000000..b8a0f926 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette-0.19.1.dist-info/top_level.txt @@ -0,0 +1 @@ +starlette diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/__init__.py new file mode 100644 index 00000000..4c1ca3c8 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/__init__.py @@ -0,0 +1 @@ +__version__ = "0.19.1" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_compat.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_compat.py new file mode 100644 index 00000000..11656191 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_compat.py @@ -0,0 +1,29 @@ +import hashlib + +# Compat wrapper to always include the `usedforsecurity=...` parameter, +# which is only added from Python 3.9 onwards. +# We use this flag to indicate that we use `md5` hashes only for non-security +# cases (our ETag checksums). +# If we don't indicate that we're using MD5 for non-security related reasons, +# then attempting to use this function will raise an error when used +# environments which enable a strict "FIPs mode". +# +# See issue: https://github.com/encode/starlette/issues/1365 +try: + + # check if the Python version supports the parameter + # using usedforsecurity=False to avoid an exception on FIPS systems + # that reject usedforsecurity=True + hashlib.md5(b"data", usedforsecurity=False) # type: ignore[call-arg] + + def md5_hexdigest( + data: bytes, *, usedforsecurity: bool = True + ) -> str: # pragma: no cover + return hashlib.md5( # type: ignore[call-arg] + data, usedforsecurity=usedforsecurity + ).hexdigest() + +except TypeError: # pragma: no cover + + def md5_hexdigest(data: bytes, *, usedforsecurity: bool = True) -> str: + return hashlib.md5(data).hexdigest() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_pep562.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_pep562.py new file mode 100644 index 00000000..a4757eac --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/_pep562.py @@ -0,0 +1,62 @@ +# flake8: noqa +""" +Backport of PEP 562. +https://pypi.org/search/?q=pep562 +Licensed under MIT +Copyright (c) 2018 Isaac Muse +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 sys +from typing import Any, Callable, List, Optional + + +class Pep562: + """ + Backport of PEP 562 . + Wraps the module in a class that exposes the mechanics to override `__dir__` and `__getattr__`. + The given module will be searched for overrides of `__dir__` and `__getattr__` and use them when needed. + """ + + def __init__(self, name: str) -> None: # pragma: no cover + """Acquire `__getattr__` and `__dir__`, but only replace module for versions less than Python 3.7.""" + + self._module = sys.modules[name] + self._get_attr = getattr(self._module, "__getattr__", None) + self._get_dir: Optional[Callable[..., List[str]]] = getattr( + self._module, "__dir__", None + ) + sys.modules[name] = self # type: ignore[assignment] + + def __dir__(self) -> List[str]: # pragma: no cover + """Return the overridden `dir` if one was provided, else apply `dir` to the module.""" + + return self._get_dir() if self._get_dir else dir(self._module) + + def __getattr__(self, name: str) -> Any: # pragma: no cover + """ + Attempt to retrieve the attribute from the module, and if missing, use the overridden function if present. + """ + + try: + return getattr(self._module, name) + except AttributeError: + if self._get_attr: + return self._get_attr(name) + raise + + +def pep562(module_name: str) -> None: # pragma: no cover + """Helper function to apply PEP 562.""" + + if sys.version_info < (3, 7): + Pep562(module_name) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/applications.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/applications.py new file mode 100644 index 00000000..8c515444 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/applications.py @@ -0,0 +1,283 @@ +import typing + +from starlette.datastructures import State, URLPath +from starlette.exceptions import ExceptionMiddleware +from starlette.middleware import Middleware +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.middleware.errors import ServerErrorMiddleware +from starlette.requests import Request +from starlette.responses import Response +from starlette.routing import BaseRoute, Router +from starlette.types import ASGIApp, Receive, Scope, Send + + +class Starlette: + """ + Creates an application instance. + + **Parameters:** + + * **debug** - Boolean indicating if debug tracebacks should be returned on errors. + * **routes** - A list of routes to serve incoming HTTP and WebSocket requests. + * **middleware** - A list of middleware to run for every request. A starlette + application will always automatically include two middleware classes. + `ServerErrorMiddleware` is added as the very outermost middleware, to handle + any uncaught errors occurring anywhere in the entire stack. + `ExceptionMiddleware` is added as the very innermost middleware, to deal + with handled exception cases occurring in the routing or endpoints. + * **exception_handlers** - A mapping of either integer status codes, + or exception class types onto callables which handle the exceptions. + Exception handler callables should be of the form + `handler(request, exc) -> response` and may be be either standard functions, or + async functions. + * **on_startup** - A list of callables to run on application startup. + Startup handler callables do not take any arguments, and may be be either + standard functions, or async functions. + * **on_shutdown** - A list of callables to run on application shutdown. + Shutdown handler callables do not take any arguments, and may be be either + standard functions, or async functions. + """ + + def __init__( + self, + debug: bool = False, + routes: typing.Optional[typing.Sequence[BaseRoute]] = None, + middleware: typing.Optional[typing.Sequence[Middleware]] = None, + exception_handlers: typing.Optional[ + typing.Mapping[ + typing.Any, + typing.Callable[ + [Request, Exception], + typing.Union[Response, typing.Awaitable[Response]], + ], + ] + ] = None, + on_startup: typing.Optional[typing.Sequence[typing.Callable]] = None, + on_shutdown: typing.Optional[typing.Sequence[typing.Callable]] = None, + lifespan: typing.Optional[ + typing.Callable[["Starlette"], typing.AsyncContextManager] + ] = None, + ) -> None: + # The lifespan context function is a newer style that replaces + # on_startup / on_shutdown handlers. Use one or the other, not both. + assert lifespan is None or ( + on_startup is None and on_shutdown is None + ), "Use either 'lifespan' or 'on_startup'/'on_shutdown', not both." + + self._debug = debug + self.state = State() + self.router = Router( + routes, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan + ) + self.exception_handlers = ( + {} if exception_handlers is None else dict(exception_handlers) + ) + self.user_middleware = [] if middleware is None else list(middleware) + self.middleware_stack = self.build_middleware_stack() + + def build_middleware_stack(self) -> ASGIApp: + debug = self.debug + error_handler = None + exception_handlers: typing.Dict[ + typing.Any, typing.Callable[[Request, Exception], Response] + ] = {} + + for key, value in self.exception_handlers.items(): + if key in (500, Exception): + error_handler = value + else: + exception_handlers[key] = value + + middleware = ( + [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] + + self.user_middleware + + [ + Middleware( + ExceptionMiddleware, handlers=exception_handlers, debug=debug + ) + ] + ) + + app = self.router + for cls, options in reversed(middleware): + app = cls(app=app, **options) + return app + + @property + def routes(self) -> typing.List[BaseRoute]: + return self.router.routes + + @property + def debug(self) -> bool: + return self._debug + + @debug.setter + def debug(self, value: bool) -> None: + self._debug = value + self.middleware_stack = self.build_middleware_stack() + + def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: + return self.router.url_path_for(name, **path_params) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + scope["app"] = self + await self.middleware_stack(scope, receive, send) + + # The following usages are now discouraged in favour of configuration + # during Starlette.__init__(...) + def on_event(self, event_type: str) -> typing.Callable: # pragma: nocover + return self.router.on_event(event_type) + + def mount( + self, path: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: nocover + """ + We no longer document this API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + Mount(path, ...), + ... + ] + + app = Starlette(routes=routes) + """ + + self.router.mount(path, app=app, name=name) + + def host( + self, host: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + """ + We no longer document this API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + Host(path, ...), + ... + ] + + app = Starlette(routes=routes) + """ + + self.router.host(host, app=app, name=name) + + def add_middleware( + self, middleware_class: type, **options: typing.Any + ) -> None: # pragma: no cover + self.user_middleware.insert(0, Middleware(middleware_class, **options)) + self.middleware_stack = self.build_middleware_stack() + + def add_exception_handler( + self, + exc_class_or_status_code: typing.Union[int, typing.Type[Exception]], + handler: typing.Callable, + ) -> None: # pragma: no cover + self.exception_handlers[exc_class_or_status_code] = handler + self.middleware_stack = self.build_middleware_stack() + + def add_event_handler( + self, event_type: str, func: typing.Callable + ) -> None: # pragma: no cover + self.router.add_event_handler(event_type, func) + + def add_route( + self, + path: str, + route: typing.Callable, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> None: # pragma: no cover + self.router.add_route( + path, route, methods=methods, name=name, include_in_schema=include_in_schema + ) + + def add_websocket_route( + self, path: str, route: typing.Callable, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + self.router.add_websocket_route(path, route, name=name) + + def exception_handler( + self, exc_class_or_status_code: typing.Union[int, typing.Type[Exception]] + ) -> typing.Callable: # pragma: nocover + def decorator(func: typing.Callable) -> typing.Callable: + self.add_exception_handler(exc_class_or_status_code, func) + return func + + return decorator + + def route( + self, + path: str, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> typing.Callable: # pragma: nocover + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + Route(path, endpoint=..., ...), + ... + ] + + app = Starlette(routes=routes) + """ + + def decorator(func: typing.Callable) -> typing.Callable: + self.router.add_route( + path, + func, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + return func + + return decorator + + def websocket_route( + self, path: str, name: typing.Optional[str] = None + ) -> typing.Callable: # pragma: nocover + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + WebSocketRoute(path, endpoint=..., ...), + ... + ] + + app = Starlette(routes=routes) + """ + + def decorator(func: typing.Callable) -> typing.Callable: + self.router.add_websocket_route(path, func, name=name) + return func + + return decorator + + def middleware(self, middleware_type: str) -> typing.Callable: # pragma: nocover + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + middleware = [ + Middleware(...), + ... + ] + + app = Starlette(middleware=middleware) + """ + + assert ( + middleware_type == "http" + ), 'Currently only middleware("http") is supported.' + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_middleware(BaseHTTPMiddleware, dispatch=func) + return func + + return decorator diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/authentication.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/authentication.py new file mode 100644 index 00000000..17f4a5ea --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/authentication.py @@ -0,0 +1,151 @@ +import asyncio +import functools +import inspect +import typing +from urllib.parse import urlencode + +from starlette.exceptions import HTTPException +from starlette.requests import HTTPConnection, Request +from starlette.responses import RedirectResponse, Response +from starlette.websockets import WebSocket + + +def has_required_scope(conn: HTTPConnection, scopes: typing.Sequence[str]) -> bool: + for scope in scopes: + if scope not in conn.auth.scopes: + return False + return True + + +def requires( + scopes: typing.Union[str, typing.Sequence[str]], + status_code: int = 403, + redirect: typing.Optional[str] = None, +) -> typing.Callable: + scopes_list = [scopes] if isinstance(scopes, str) else list(scopes) + + def decorator(func: typing.Callable) -> typing.Callable: + sig = inspect.signature(func) + for idx, parameter in enumerate(sig.parameters.values()): + if parameter.name == "request" or parameter.name == "websocket": + type_ = parameter.name + break + else: + raise Exception( + f'No "request" or "websocket" argument on function "{func}"' + ) + + if type_ == "websocket": + # Handle websocket functions. (Always async) + @functools.wraps(func) + async def websocket_wrapper( + *args: typing.Any, **kwargs: typing.Any + ) -> None: + websocket = kwargs.get( + "websocket", args[idx] if idx < len(args) else None + ) + assert isinstance(websocket, WebSocket) + + if not has_required_scope(websocket, scopes_list): + await websocket.close() + else: + await func(*args, **kwargs) + + return websocket_wrapper + + elif asyncio.iscoroutinefunction(func): + # Handle async request/response functions. + @functools.wraps(func) + async def async_wrapper( + *args: typing.Any, **kwargs: typing.Any + ) -> Response: + request = kwargs.get("request", args[idx] if idx < len(args) else None) + assert isinstance(request, Request) + + if not has_required_scope(request, scopes_list): + if redirect is not None: + orig_request_qparam = urlencode({"next": str(request.url)}) + next_url = "{redirect_path}?{orig_request}".format( + redirect_path=request.url_for(redirect), + orig_request=orig_request_qparam, + ) + return RedirectResponse(url=next_url, status_code=303) + raise HTTPException(status_code=status_code) + return await func(*args, **kwargs) + + return async_wrapper + + else: + # Handle sync request/response functions. + @functools.wraps(func) + def sync_wrapper(*args: typing.Any, **kwargs: typing.Any) -> Response: + request = kwargs.get("request", args[idx] if idx < len(args) else None) + assert isinstance(request, Request) + + if not has_required_scope(request, scopes_list): + if redirect is not None: + orig_request_qparam = urlencode({"next": str(request.url)}) + next_url = "{redirect_path}?{orig_request}".format( + redirect_path=request.url_for(redirect), + orig_request=orig_request_qparam, + ) + return RedirectResponse(url=next_url, status_code=303) + raise HTTPException(status_code=status_code) + return func(*args, **kwargs) + + return sync_wrapper + + return decorator + + +class AuthenticationError(Exception): + pass + + +class AuthenticationBackend: + async def authenticate( + self, conn: HTTPConnection + ) -> typing.Optional[typing.Tuple["AuthCredentials", "BaseUser"]]: + raise NotImplementedError() # pragma: no cover + + +class AuthCredentials: + def __init__(self, scopes: typing.Optional[typing.Sequence[str]] = None): + self.scopes = [] if scopes is None else list(scopes) + + +class BaseUser: + @property + def is_authenticated(self) -> bool: + raise NotImplementedError() # pragma: no cover + + @property + def display_name(self) -> str: + raise NotImplementedError() # pragma: no cover + + @property + def identity(self) -> str: + raise NotImplementedError() # pragma: no cover + + +class SimpleUser(BaseUser): + def __init__(self, username: str) -> None: + self.username = username + + @property + def is_authenticated(self) -> bool: + return True + + @property + def display_name(self) -> str: + return self.username + + +class UnauthenticatedUser(BaseUser): + @property + def is_authenticated(self) -> bool: + return False + + @property + def display_name(self) -> str: + return "" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/background.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/background.py new file mode 100644 index 00000000..145324e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/background.py @@ -0,0 +1,43 @@ +import asyncio +import sys +import typing + +if sys.version_info >= (3, 10): # pragma: no cover + from typing import ParamSpec +else: # pragma: no cover + from typing_extensions import ParamSpec + +from starlette.concurrency import run_in_threadpool + +P = ParamSpec("P") + + +class BackgroundTask: + def __init__( + self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs + ) -> None: + self.func = func + self.args = args + self.kwargs = kwargs + self.is_async = asyncio.iscoroutinefunction(func) + + async def __call__(self) -> None: + if self.is_async: + await self.func(*self.args, **self.kwargs) + else: + await run_in_threadpool(self.func, *self.args, **self.kwargs) + + +class BackgroundTasks(BackgroundTask): + def __init__(self, tasks: typing.Optional[typing.Sequence[BackgroundTask]] = None): + self.tasks = list(tasks) if tasks else [] + + def add_task( + self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs + ) -> None: + task = BackgroundTask(func, *args, **kwargs) + self.tasks.append(task) + + async def __call__(self) -> None: + for task in self.tasks: + await task() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/concurrency.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/concurrency.py new file mode 100644 index 00000000..5c76cb3d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/concurrency.py @@ -0,0 +1,65 @@ +import functools +import sys +import typing +import warnings + +import anyio + +if sys.version_info >= (3, 10): # pragma: no cover + from typing import ParamSpec +else: # pragma: no cover + from typing_extensions import ParamSpec + + +T = typing.TypeVar("T") +P = ParamSpec("P") + + +async def run_until_first_complete(*args: typing.Tuple[typing.Callable, dict]) -> None: + warnings.warn( + "run_until_first_complete is deprecated " + "and will be removed in a future version.", + DeprecationWarning, + ) + + async with anyio.create_task_group() as task_group: + + async def run(func: typing.Callable[[], typing.Coroutine]) -> None: + await func() + task_group.cancel_scope.cancel() + + for func, kwargs in args: + task_group.start_soon(run, functools.partial(func, **kwargs)) + + +async def run_in_threadpool( + func: typing.Callable[P, T], *args: P.args, **kwargs: P.kwargs +) -> T: + if kwargs: # pragma: no cover + # run_sync doesn't accept 'kwargs', so bind them in here + func = functools.partial(func, **kwargs) + return await anyio.to_thread.run_sync(func, *args) + + +class _StopIteration(Exception): + pass + + +def _next(iterator: typing.Iterator[T]) -> T: + # We can't raise `StopIteration` from within the threadpool iterator + # and catch it outside that context, so we coerce them into a different + # exception type. + try: + return next(iterator) + except StopIteration: + raise _StopIteration + + +async def iterate_in_threadpool( + iterator: typing.Iterator[T], +) -> typing.AsyncIterator[T]: + while True: + try: + yield await anyio.to_thread.run_sync(_next, iterator) + except _StopIteration: + break diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/config.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/config.py new file mode 100644 index 00000000..e9e809c7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/config.py @@ -0,0 +1,144 @@ +import os +import typing +from collections.abc import MutableMapping +from pathlib import Path + + +class undefined: + pass + + +class EnvironError(Exception): + pass + + +class Environ(MutableMapping): + def __init__(self, environ: typing.MutableMapping = os.environ): + self._environ = environ + self._has_been_read: typing.Set[typing.Any] = set() + + def __getitem__(self, key: typing.Any) -> typing.Any: + self._has_been_read.add(key) + return self._environ.__getitem__(key) + + def __setitem__(self, key: typing.Any, value: typing.Any) -> None: + if key in self._has_been_read: + raise EnvironError( + f"Attempting to set environ['{key}'], but the value has already been " + "read." + ) + self._environ.__setitem__(key, value) + + def __delitem__(self, key: typing.Any) -> None: + if key in self._has_been_read: + raise EnvironError( + f"Attempting to delete environ['{key}'], but the value has already " + "been read." + ) + self._environ.__delitem__(key) + + def __iter__(self) -> typing.Iterator: + return iter(self._environ) + + def __len__(self) -> int: + return len(self._environ) + + +environ = Environ() + +T = typing.TypeVar("T") + + +class Config: + def __init__( + self, + env_file: typing.Optional[typing.Union[str, Path]] = None, + environ: typing.Mapping[str, str] = environ, + ) -> None: + self.environ = environ + self.file_values: typing.Dict[str, str] = {} + if env_file is not None and os.path.isfile(env_file): + self.file_values = self._read_file(env_file) + + @typing.overload + def __call__( + self, key: str, cast: typing.Type[T], default: T = ... + ) -> T: # pragma: no cover + ... + + @typing.overload + def __call__( + self, key: str, cast: typing.Type[str] = ..., default: str = ... + ) -> str: # pragma: no cover + ... + + @typing.overload + def __call__( + self, + key: str, + cast: typing.Callable[[typing.Any], T] = ..., + default: typing.Any = ..., + ) -> T: # pragma: no cover + ... + + @typing.overload + def __call__( + self, key: str, cast: typing.Type[str] = ..., default: T = ... + ) -> typing.Union[T, str]: # pragma: no cover + ... + + def __call__( + self, + key: str, + cast: typing.Optional[typing.Callable] = None, + default: typing.Any = undefined, + ) -> typing.Any: + return self.get(key, cast, default) + + def get( + self, + key: str, + cast: typing.Optional[typing.Callable] = None, + default: typing.Any = undefined, + ) -> typing.Any: + if key in self.environ: + value = self.environ[key] + return self._perform_cast(key, value, cast) + if key in self.file_values: + value = self.file_values[key] + return self._perform_cast(key, value, cast) + if default is not undefined: + return self._perform_cast(key, default, cast) + raise KeyError(f"Config '{key}' is missing, and has no default.") + + def _read_file(self, file_name: typing.Union[str, Path]) -> typing.Dict[str, str]: + file_values: typing.Dict[str, str] = {} + with open(file_name) as input_file: + for line in input_file.readlines(): + line = line.strip() + if "=" in line and not line.startswith("#"): + key, value = line.split("=", 1) + key = key.strip() + value = value.strip().strip("\"'") + file_values[key] = value + return file_values + + def _perform_cast( + self, key: str, value: typing.Any, cast: typing.Optional[typing.Callable] = None + ) -> typing.Any: + if cast is None or value is None: + return value + elif cast is bool and isinstance(value, str): + mapping = {"true": True, "1": True, "false": False, "0": False} + value = value.lower() + if value not in mapping: + raise ValueError( + f"Config '{key}' has value '{value}'. Not a valid bool." + ) + return mapping[value] + try: + return cast(value) + except (TypeError, ValueError): + raise ValueError( + f"Config '{key}' has value '{value}'. Not a valid {cast.__name__}." + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/convertors.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/convertors.py new file mode 100644 index 00000000..e3c03d07 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/convertors.py @@ -0,0 +1,87 @@ +import math +import typing +import uuid + +T = typing.TypeVar("T") + + +class Convertor(typing.Generic[T]): + regex: typing.ClassVar[str] = "" + + def convert(self, value: str) -> T: + raise NotImplementedError() # pragma: no cover + + def to_string(self, value: T) -> str: + raise NotImplementedError() # pragma: no cover + + +class StringConvertor(Convertor): + regex = "[^/]+" + + def convert(self, value: str) -> str: + return value + + def to_string(self, value: str) -> str: + value = str(value) + assert "/" not in value, "May not contain path separators" + assert value, "Must not be empty" + return value + + +class PathConvertor(Convertor): + regex = ".*" + + def convert(self, value: str) -> str: + return str(value) + + def to_string(self, value: str) -> str: + return str(value) + + +class IntegerConvertor(Convertor): + regex = "[0-9]+" + + def convert(self, value: str) -> int: + return int(value) + + def to_string(self, value: int) -> str: + value = int(value) + assert value >= 0, "Negative integers are not supported" + return str(value) + + +class FloatConvertor(Convertor): + regex = "[0-9]+(.[0-9]+)?" + + def convert(self, value: str) -> float: + return float(value) + + def to_string(self, value: float) -> str: + value = float(value) + assert value >= 0.0, "Negative floats are not supported" + assert not math.isnan(value), "NaN values are not supported" + assert not math.isinf(value), "Infinite values are not supported" + return ("%0.20f" % value).rstrip("0").rstrip(".") + + +class UUIDConvertor(Convertor): + regex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + + def convert(self, value: str) -> uuid.UUID: + return uuid.UUID(value) + + def to_string(self, value: uuid.UUID) -> str: + return str(value) + + +CONVERTOR_TYPES = { + "str": StringConvertor(), + "path": PathConvertor(), + "int": IntegerConvertor(), + "float": FloatConvertor(), + "uuid": UUIDConvertor(), +} + + +def register_url_convertor(key: str, convertor: Convertor) -> None: + CONVERTOR_TYPES[key] = convertor diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/datastructures.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/datastructures.py new file mode 100644 index 00000000..59863282 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/datastructures.py @@ -0,0 +1,696 @@ +import tempfile +import typing +from collections.abc import Sequence +from shlex import shlex +from urllib.parse import SplitResult, parse_qsl, urlencode, urlsplit + +from starlette.concurrency import run_in_threadpool +from starlette.types import Scope + + +class Address(typing.NamedTuple): + host: str + port: int + + +class URL: + def __init__( + self, + url: str = "", + scope: typing.Optional[Scope] = None, + **components: typing.Any, + ) -> None: + if scope is not None: + assert not url, 'Cannot set both "url" and "scope".' + assert not components, 'Cannot set both "scope" and "**components".' + scheme = scope.get("scheme", "http") + server = scope.get("server", None) + path = scope.get("root_path", "") + scope["path"] + query_string = scope.get("query_string", b"") + + host_header = None + for key, value in scope["headers"]: + if key == b"host": + host_header = value.decode("latin-1") + break + + if host_header is not None: + url = f"{scheme}://{host_header}{path}" + elif server is None: + url = path + else: + host, port = server + default_port = {"http": 80, "https": 443, "ws": 80, "wss": 443}[scheme] + if port == default_port: + url = f"{scheme}://{host}{path}" + else: + url = f"{scheme}://{host}:{port}{path}" + + if query_string: + url += "?" + query_string.decode() + elif components: + assert not url, 'Cannot set both "url" and "**components".' + url = URL("").replace(**components).components.geturl() + + self._url = url + + @property + def components(self) -> SplitResult: + if not hasattr(self, "_components"): + self._components = urlsplit(self._url) + return self._components + + @property + def scheme(self) -> str: + return self.components.scheme + + @property + def netloc(self) -> str: + return self.components.netloc + + @property + def path(self) -> str: + return self.components.path + + @property + def query(self) -> str: + return self.components.query + + @property + def fragment(self) -> str: + return self.components.fragment + + @property + def username(self) -> typing.Union[None, str]: + return self.components.username + + @property + def password(self) -> typing.Union[None, str]: + return self.components.password + + @property + def hostname(self) -> typing.Union[None, str]: + return self.components.hostname + + @property + def port(self) -> typing.Optional[int]: + return self.components.port + + @property + def is_secure(self) -> bool: + return self.scheme in ("https", "wss") + + def replace(self, **kwargs: typing.Any) -> "URL": + if ( + "username" in kwargs + or "password" in kwargs + or "hostname" in kwargs + or "port" in kwargs + ): + hostname = kwargs.pop("hostname", self.hostname) + port = kwargs.pop("port", self.port) + username = kwargs.pop("username", self.username) + password = kwargs.pop("password", self.password) + + netloc = hostname + if port is not None: + netloc += f":{port}" + if username is not None: + userpass = username + if password is not None: + userpass += f":{password}" + netloc = f"{userpass}@{netloc}" + + kwargs["netloc"] = netloc + + components = self.components._replace(**kwargs) + return self.__class__(components.geturl()) + + def include_query_params(self, **kwargs: typing.Any) -> "URL": + params = MultiDict(parse_qsl(self.query, keep_blank_values=True)) + params.update({str(key): str(value) for key, value in kwargs.items()}) + query = urlencode(params.multi_items()) + return self.replace(query=query) + + def replace_query_params(self, **kwargs: typing.Any) -> "URL": + query = urlencode([(str(key), str(value)) for key, value in kwargs.items()]) + return self.replace(query=query) + + def remove_query_params( + self, keys: typing.Union[str, typing.Sequence[str]] + ) -> "URL": + if isinstance(keys, str): + keys = [keys] + params = MultiDict(parse_qsl(self.query, keep_blank_values=True)) + for key in keys: + params.pop(key, None) + query = urlencode(params.multi_items()) + return self.replace(query=query) + + def __eq__(self, other: typing.Any) -> bool: + return str(self) == str(other) + + def __str__(self) -> str: + return self._url + + def __repr__(self) -> str: + url = str(self) + if self.password: + url = str(self.replace(password="********")) + return f"{self.__class__.__name__}({repr(url)})" + + +class URLPath(str): + """ + A URL path string that may also hold an associated protocol and/or host. + Used by the routing to return `url_path_for` matches. + """ + + def __new__(cls, path: str, protocol: str = "", host: str = "") -> "URLPath": + assert protocol in ("http", "websocket", "") + return str.__new__(cls, path) + + def __init__(self, path: str, protocol: str = "", host: str = "") -> None: + self.protocol = protocol + self.host = host + + def make_absolute_url(self, base_url: typing.Union[str, URL]) -> str: + if isinstance(base_url, str): + base_url = URL(base_url) + if self.protocol: + scheme = { + "http": {True: "https", False: "http"}, + "websocket": {True: "wss", False: "ws"}, + }[self.protocol][base_url.is_secure] + else: + scheme = base_url.scheme + + netloc = self.host or base_url.netloc + path = base_url.path.rstrip("/") + str(self) + return str(URL(scheme=scheme, netloc=netloc, path=path)) + + +class Secret: + """ + Holds a string value that should not be revealed in tracebacks etc. + You should cast the value to `str` at the point it is required. + """ + + def __init__(self, value: str): + self._value = value + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + return f"{class_name}('**********')" + + def __str__(self) -> str: + return self._value + + +class CommaSeparatedStrings(Sequence): + def __init__(self, value: typing.Union[str, typing.Sequence[str]]): + if isinstance(value, str): + splitter = shlex(value, posix=True) + splitter.whitespace = "," + splitter.whitespace_split = True + self._items = [item.strip() for item in splitter] + else: + self._items = list(value) + + def __len__(self) -> int: + return len(self._items) + + def __getitem__(self, index: typing.Union[int, slice]) -> typing.Any: + return self._items[index] + + def __iter__(self) -> typing.Iterator[str]: + return iter(self._items) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + items = [item for item in self] + return f"{class_name}({items!r})" + + def __str__(self) -> str: + return ", ".join(repr(item) for item in self) + + +class ImmutableMultiDict(typing.Mapping): + def __init__( + self, + *args: typing.Union[ + "ImmutableMultiDict", + typing.Mapping, + typing.List[typing.Tuple[typing.Any, typing.Any]], + ], + **kwargs: typing.Any, + ) -> None: + assert len(args) < 2, "Too many arguments." + + value = args[0] if args else [] + if kwargs: + value = ( + ImmutableMultiDict(value).multi_items() + + ImmutableMultiDict(kwargs).multi_items() + ) + + if not value: + _items: typing.List[typing.Tuple[typing.Any, typing.Any]] = [] + elif hasattr(value, "multi_items"): + value = typing.cast(ImmutableMultiDict, value) + _items = list(value.multi_items()) + elif hasattr(value, "items"): + value = typing.cast(typing.Mapping, value) + _items = list(value.items()) + else: + value = typing.cast( + typing.List[typing.Tuple[typing.Any, typing.Any]], value + ) + _items = list(value) + + self._dict = {k: v for k, v in _items} + self._list = _items + + def getlist(self, key: typing.Any) -> typing.List[typing.Any]: + return [item_value for item_key, item_value in self._list if item_key == key] + + def keys(self) -> typing.KeysView: + return self._dict.keys() + + def values(self) -> typing.ValuesView: + return self._dict.values() + + def items(self) -> typing.ItemsView: + return self._dict.items() + + def multi_items(self) -> typing.List[typing.Tuple[str, str]]: + return list(self._list) + + def get(self, key: typing.Any, default: typing.Any = None) -> typing.Any: + if key in self._dict: + return self._dict[key] + return default + + def __getitem__(self, key: typing.Any) -> str: + return self._dict[key] + + def __contains__(self, key: typing.Any) -> bool: + return key in self._dict + + def __iter__(self) -> typing.Iterator[typing.Any]: + return iter(self.keys()) + + def __len__(self) -> int: + return len(self._dict) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, self.__class__): + return False + return sorted(self._list) == sorted(other._list) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + items = self.multi_items() + return f"{class_name}({items!r})" + + +class MultiDict(ImmutableMultiDict): + def __setitem__(self, key: typing.Any, value: typing.Any) -> None: + self.setlist(key, [value]) + + def __delitem__(self, key: typing.Any) -> None: + self._list = [(k, v) for k, v in self._list if k != key] + del self._dict[key] + + def pop(self, key: typing.Any, default: typing.Any = None) -> typing.Any: + self._list = [(k, v) for k, v in self._list if k != key] + return self._dict.pop(key, default) + + def popitem(self) -> typing.Tuple: + key, value = self._dict.popitem() + self._list = [(k, v) for k, v in self._list if k != key] + return key, value + + def poplist(self, key: typing.Any) -> typing.List: + values = [v for k, v in self._list if k == key] + self.pop(key) + return values + + def clear(self) -> None: + self._dict.clear() + self._list.clear() + + def setdefault(self, key: typing.Any, default: typing.Any = None) -> typing.Any: + if key not in self: + self._dict[key] = default + self._list.append((key, default)) + + return self[key] + + def setlist(self, key: typing.Any, values: typing.List) -> None: + if not values: + self.pop(key, None) + else: + existing_items = [(k, v) for (k, v) in self._list if k != key] + self._list = existing_items + [(key, value) for value in values] + self._dict[key] = values[-1] + + def append(self, key: typing.Any, value: typing.Any) -> None: + self._list.append((key, value)) + self._dict[key] = value + + def update( + self, + *args: typing.Union[ + "MultiDict", + typing.Mapping, + typing.List[typing.Tuple[typing.Any, typing.Any]], + ], + **kwargs: typing.Any, + ) -> None: + value = MultiDict(*args, **kwargs) + existing_items = [(k, v) for (k, v) in self._list if k not in value.keys()] + self._list = existing_items + value.multi_items() + self._dict.update(value) + + +class QueryParams(ImmutableMultiDict): + """ + An immutable multidict. + """ + + def __init__( + self, + *args: typing.Union[ + "ImmutableMultiDict", + typing.Mapping, + typing.List[typing.Tuple[typing.Any, typing.Any]], + str, + bytes, + ], + **kwargs: typing.Any, + ) -> None: + assert len(args) < 2, "Too many arguments." + + value = args[0] if args else [] + + if isinstance(value, str): + super().__init__(parse_qsl(value, keep_blank_values=True), **kwargs) + elif isinstance(value, bytes): + super().__init__( + parse_qsl(value.decode("latin-1"), keep_blank_values=True), **kwargs + ) + else: + super().__init__(*args, **kwargs) # type: ignore + self._list = [(str(k), str(v)) for k, v in self._list] + self._dict = {str(k): str(v) for k, v in self._dict.items()} + + def __str__(self) -> str: + return urlencode(self._list) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + query_string = str(self) + return f"{class_name}({query_string!r})" + + +class UploadFile: + """ + An uploaded file included as part of the request data. + """ + + spool_max_size = 1024 * 1024 + file: typing.BinaryIO + headers: "Headers" + + def __init__( + self, + filename: str, + file: typing.Optional[typing.BinaryIO] = None, + content_type: str = "", + *, + headers: "typing.Optional[Headers]" = None, + ) -> None: + self.filename = filename + self.content_type = content_type + if file is None: + self.file = tempfile.SpooledTemporaryFile(max_size=self.spool_max_size) # type: ignore # noqa: E501 + else: + self.file = file + self.headers = headers or Headers() + + @property + def _in_memory(self) -> bool: + rolled_to_disk = getattr(self.file, "_rolled", True) + return not rolled_to_disk + + async def write(self, data: bytes) -> None: + if self._in_memory: + self.file.write(data) + else: + await run_in_threadpool(self.file.write, data) + + async def read(self, size: int = -1) -> bytes: + if self._in_memory: + return self.file.read(size) + return await run_in_threadpool(self.file.read, size) + + async def seek(self, offset: int) -> None: + if self._in_memory: + self.file.seek(offset) + else: + await run_in_threadpool(self.file.seek, offset) + + async def close(self) -> None: + if self._in_memory: + self.file.close() + else: + await run_in_threadpool(self.file.close) + + +class FormData(ImmutableMultiDict): + """ + An immutable multidict, containing both file uploads and text input. + """ + + def __init__( + self, + *args: typing.Union[ + "FormData", + typing.Mapping[str, typing.Union[str, UploadFile]], + typing.List[typing.Tuple[str, typing.Union[str, UploadFile]]], + ], + **kwargs: typing.Union[str, UploadFile], + ) -> None: + super().__init__(*args, **kwargs) + + async def close(self) -> None: + for key, value in self.multi_items(): + if isinstance(value, UploadFile): + await value.close() + + +class Headers(typing.Mapping[str, str]): + """ + An immutable, case-insensitive multidict. + """ + + def __init__( + self, + headers: typing.Optional[typing.Mapping[str, str]] = None, + raw: typing.Optional[typing.List[typing.Tuple[bytes, bytes]]] = None, + scope: typing.Optional[typing.Mapping[str, typing.Any]] = None, + ) -> None: + self._list: typing.List[typing.Tuple[bytes, bytes]] = [] + if headers is not None: + assert raw is None, 'Cannot set both "headers" and "raw".' + assert scope is None, 'Cannot set both "headers" and "scope".' + self._list = [ + (key.lower().encode("latin-1"), value.encode("latin-1")) + for key, value in headers.items() + ] + elif raw is not None: + assert scope is None, 'Cannot set both "raw" and "scope".' + self._list = raw + elif scope is not None: + self._list = scope["headers"] + + @property + def raw(self) -> typing.List[typing.Tuple[bytes, bytes]]: + return list(self._list) + + def keys(self) -> typing.List[str]: # type: ignore + return [key.decode("latin-1") for key, value in self._list] + + def values(self) -> typing.List[str]: # type: ignore + return [value.decode("latin-1") for key, value in self._list] + + def items(self) -> typing.List[typing.Tuple[str, str]]: # type: ignore + return [ + (key.decode("latin-1"), value.decode("latin-1")) + for key, value in self._list + ] + + def get(self, key: str, default: typing.Any = None) -> typing.Any: + try: + return self[key] + except KeyError: + return default + + def getlist(self, key: str) -> typing.List[str]: + get_header_key = key.lower().encode("latin-1") + return [ + item_value.decode("latin-1") + for item_key, item_value in self._list + if item_key == get_header_key + ] + + def mutablecopy(self) -> "MutableHeaders": + return MutableHeaders(raw=self._list[:]) + + def __getitem__(self, key: str) -> str: + get_header_key = key.lower().encode("latin-1") + for header_key, header_value in self._list: + if header_key == get_header_key: + return header_value.decode("latin-1") + raise KeyError(key) + + def __contains__(self, key: typing.Any) -> bool: + get_header_key = key.lower().encode("latin-1") + for header_key, header_value in self._list: + if header_key == get_header_key: + return True + return False + + def __iter__(self) -> typing.Iterator[typing.Any]: + return iter(self.keys()) + + def __len__(self) -> int: + return len(self._list) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, Headers): + return False + return sorted(self._list) == sorted(other._list) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + as_dict = dict(self.items()) + if len(as_dict) == len(self): + return f"{class_name}({as_dict!r})" + return f"{class_name}(raw={self.raw!r})" + + +class MutableHeaders(Headers): + def __setitem__(self, key: str, value: str) -> None: + """ + Set the header `key` to `value`, removing any duplicate entries. + Retains insertion order. + """ + set_key = key.lower().encode("latin-1") + set_value = value.encode("latin-1") + + found_indexes = [] + for idx, (item_key, item_value) in enumerate(self._list): + if item_key == set_key: + found_indexes.append(idx) + + for idx in reversed(found_indexes[1:]): + del self._list[idx] + + if found_indexes: + idx = found_indexes[0] + self._list[idx] = (set_key, set_value) + else: + self._list.append((set_key, set_value)) + + def __delitem__(self, key: str) -> None: + """ + Remove the header `key`. + """ + del_key = key.lower().encode("latin-1") + + pop_indexes = [] + for idx, (item_key, item_value) in enumerate(self._list): + if item_key == del_key: + pop_indexes.append(idx) + + for idx in reversed(pop_indexes): + del self._list[idx] + + def __ior__(self, other: typing.Mapping) -> "MutableHeaders": + if not isinstance(other, typing.Mapping): + raise TypeError(f"Expected a mapping but got {other.__class__.__name__}") + self.update(other) + return self + + def __or__(self, other: typing.Mapping) -> "MutableHeaders": + if not isinstance(other, typing.Mapping): + raise TypeError(f"Expected a mapping but got {other.__class__.__name__}") + new = self.mutablecopy() + new.update(other) + return new + + @property + def raw(self) -> typing.List[typing.Tuple[bytes, bytes]]: + return self._list + + def setdefault(self, key: str, value: str) -> str: + """ + If the header `key` does not exist, then set it to `value`. + Returns the header value. + """ + set_key = key.lower().encode("latin-1") + set_value = value.encode("latin-1") + + for idx, (item_key, item_value) in enumerate(self._list): + if item_key == set_key: + return item_value.decode("latin-1") + self._list.append((set_key, set_value)) + return value + + def update(self, other: typing.Mapping) -> None: + for key, val in other.items(): + self[key] = val + + def append(self, key: str, value: str) -> None: + """ + Append a header, preserving any duplicate entries. + """ + append_key = key.lower().encode("latin-1") + append_value = value.encode("latin-1") + self._list.append((append_key, append_value)) + + def add_vary_header(self, vary: str) -> None: + existing = self.get("vary") + if existing is not None: + vary = ", ".join([existing, vary]) + self["vary"] = vary + + +class State: + """ + An object that can be used to store arbitrary state. + + Used for `request.state` and `app.state`. + """ + + _state: typing.Dict[str, typing.Any] + + def __init__(self, state: typing.Optional[typing.Dict[str, typing.Any]] = None): + if state is None: + state = {} + super().__setattr__("_state", state) + + def __setattr__(self, key: typing.Any, value: typing.Any) -> None: + self._state[key] = value + + def __getattr__(self, key: typing.Any) -> typing.Any: + try: + return self._state[key] + except KeyError: + message = "'{}' object has no attribute '{}'" + raise AttributeError(message.format(self.__class__.__name__, key)) + + def __delattr__(self, key: typing.Any) -> None: + del self._state[key] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/endpoints.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/endpoints.py new file mode 100644 index 00000000..f2468a32 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/endpoints.py @@ -0,0 +1,132 @@ +import asyncio +import json +import typing + +from starlette import status +from starlette.concurrency import run_in_threadpool +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import PlainTextResponse, Response +from starlette.types import Message, Receive, Scope, Send +from starlette.websockets import WebSocket + + +class HTTPEndpoint: + def __init__(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] == "http" + self.scope = scope + self.receive = receive + self.send = send + self._allowed_methods = [ + method + for method in ("GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") + if getattr(self, method.lower(), None) is not None + ] + + def __await__(self) -> typing.Generator: + return self.dispatch().__await__() + + async def dispatch(self) -> None: + request = Request(self.scope, receive=self.receive) + handler_name = ( + "get" + if request.method == "HEAD" and not hasattr(self, "head") + else request.method.lower() + ) + + handler: typing.Callable[[Request], typing.Any] = getattr( + self, handler_name, self.method_not_allowed + ) + is_async = asyncio.iscoroutinefunction(handler) + if is_async: + response = await handler(request) + else: + response = await run_in_threadpool(handler, request) + await response(self.scope, self.receive, self.send) + + async def method_not_allowed(self, request: Request) -> Response: + # If we're running inside a starlette application then raise an + # exception, so that the configurable exception handler can deal with + # returning the response. For plain ASGI apps, just return the response. + headers = {"Allow": ", ".join(self._allowed_methods)} + if "app" in self.scope: + raise HTTPException(status_code=405, headers=headers) + return PlainTextResponse("Method Not Allowed", status_code=405, headers=headers) + + +class WebSocketEndpoint: + + encoding: typing.Optional[str] = None # May be "text", "bytes", or "json". + + def __init__(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] == "websocket" + self.scope = scope + self.receive = receive + self.send = send + + def __await__(self) -> typing.Generator: + return self.dispatch().__await__() + + async def dispatch(self) -> None: + websocket = WebSocket(self.scope, receive=self.receive, send=self.send) + await self.on_connect(websocket) + + close_code = status.WS_1000_NORMAL_CLOSURE + + try: + while True: + message = await websocket.receive() + if message["type"] == "websocket.receive": + data = await self.decode(websocket, message) + await self.on_receive(websocket, data) + elif message["type"] == "websocket.disconnect": + close_code = int( + message.get("code") or status.WS_1000_NORMAL_CLOSURE + ) + break + except Exception as exc: + close_code = status.WS_1011_INTERNAL_ERROR + raise exc + finally: + await self.on_disconnect(websocket, close_code) + + async def decode(self, websocket: WebSocket, message: Message) -> typing.Any: + + if self.encoding == "text": + if "text" not in message: + await websocket.close(code=status.WS_1003_UNSUPPORTED_DATA) + raise RuntimeError("Expected text websocket messages, but got bytes") + return message["text"] + + elif self.encoding == "bytes": + if "bytes" not in message: + await websocket.close(code=status.WS_1003_UNSUPPORTED_DATA) + raise RuntimeError("Expected bytes websocket messages, but got text") + return message["bytes"] + + elif self.encoding == "json": + if message.get("text") is not None: + text = message["text"] + else: + text = message["bytes"].decode("utf-8") + + try: + return json.loads(text) + except json.decoder.JSONDecodeError: + await websocket.close(code=status.WS_1003_UNSUPPORTED_DATA) + raise RuntimeError("Malformed JSON data received.") + + assert ( + self.encoding is None + ), f"Unsupported 'encoding' attribute {self.encoding}" + return message["text"] if message.get("text") else message["bytes"] + + async def on_connect(self, websocket: WebSocket) -> None: + """Override to handle an incoming websocket connection""" + await websocket.accept() + + async def on_receive(self, websocket: WebSocket, data: typing.Any) -> None: + """Override to handle an incoming websocket message""" + + async def on_disconnect(self, websocket: WebSocket, close_code: int) -> None: + """Override to handle a disconnecting websocket""" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/exceptions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/exceptions.py new file mode 100644 index 00000000..61039c59 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/exceptions.py @@ -0,0 +1,111 @@ +import asyncio +import http +import typing + +from starlette.concurrency import run_in_threadpool +from starlette.requests import Request +from starlette.responses import PlainTextResponse, Response +from starlette.types import ASGIApp, Message, Receive, Scope, Send + + +class HTTPException(Exception): + def __init__( + self, + status_code: int, + detail: typing.Optional[str] = None, + headers: typing.Optional[dict] = None, + ) -> None: + if detail is None: + detail = http.HTTPStatus(status_code).phrase + self.status_code = status_code + self.detail = detail + self.headers = headers + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + return f"{class_name}(status_code={self.status_code!r}, detail={self.detail!r})" + + +class ExceptionMiddleware: + def __init__( + self, + app: ASGIApp, + handlers: typing.Optional[ + typing.Mapping[typing.Any, typing.Callable[[Request, Exception], Response]] + ] = None, + debug: bool = False, + ) -> None: + self.app = app + self.debug = debug # TODO: We ought to handle 404 cases if debug is set. + self._status_handlers: typing.Dict[int, typing.Callable] = {} + self._exception_handlers: typing.Dict[ + typing.Type[Exception], typing.Callable + ] = {HTTPException: self.http_exception} + if handlers is not None: + for key, value in handlers.items(): + self.add_exception_handler(key, value) + + def add_exception_handler( + self, + exc_class_or_status_code: typing.Union[int, typing.Type[Exception]], + handler: typing.Callable[[Request, Exception], Response], + ) -> None: + if isinstance(exc_class_or_status_code, int): + self._status_handlers[exc_class_or_status_code] = handler + else: + assert issubclass(exc_class_or_status_code, Exception) + self._exception_handlers[exc_class_or_status_code] = handler + + def _lookup_exception_handler( + self, exc: Exception + ) -> typing.Optional[typing.Callable]: + for cls in type(exc).__mro__: + if cls in self._exception_handlers: + return self._exception_handlers[cls] + return None + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + response_started = False + + async def sender(message: Message) -> None: + nonlocal response_started + + if message["type"] == "http.response.start": + response_started = True + await send(message) + + try: + await self.app(scope, receive, sender) + except Exception as exc: + handler = None + + if isinstance(exc, HTTPException): + handler = self._status_handlers.get(exc.status_code) + + if handler is None: + handler = self._lookup_exception_handler(exc) + + if handler is None: + raise exc + + if response_started: + msg = "Caught handled exception, but response already started." + raise RuntimeError(msg) from exc + + request = Request(scope, receive=receive) + if asyncio.iscoroutinefunction(handler): + response = await handler(request, exc) + else: + response = await run_in_threadpool(handler, request, exc) + await response(scope, receive, sender) + + def http_exception(self, request: Request, exc: HTTPException) -> Response: + if exc.status_code in {204, 304}: + return Response(status_code=exc.status_code, headers=exc.headers) + return PlainTextResponse( + exc.detail, status_code=exc.status_code, headers=exc.headers + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/formparsers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/formparsers.py new file mode 100644 index 00000000..fd194922 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/formparsers.py @@ -0,0 +1,238 @@ +import typing +from enum import Enum +from urllib.parse import unquote_plus + +from starlette.datastructures import FormData, Headers, UploadFile + +try: + import multipart + from multipart.multipart import parse_options_header +except ImportError: # pragma: nocover + parse_options_header = None + multipart = None + + +class FormMessage(Enum): + FIELD_START = 1 + FIELD_NAME = 2 + FIELD_DATA = 3 + FIELD_END = 4 + END = 5 + + +class MultiPartMessage(Enum): + PART_BEGIN = 1 + PART_DATA = 2 + PART_END = 3 + HEADER_FIELD = 4 + HEADER_VALUE = 5 + HEADER_END = 6 + HEADERS_FINISHED = 7 + END = 8 + + +def _user_safe_decode(src: bytes, codec: str) -> str: + try: + return src.decode(codec) + except (UnicodeDecodeError, LookupError): + return src.decode("latin-1") + + +class FormParser: + def __init__( + self, headers: Headers, stream: typing.AsyncGenerator[bytes, None] + ) -> None: + assert ( + multipart is not None + ), "The `python-multipart` library must be installed to use form parsing." + self.headers = headers + self.stream = stream + self.messages: typing.List[typing.Tuple[FormMessage, bytes]] = [] + + def on_field_start(self) -> None: + message = (FormMessage.FIELD_START, b"") + self.messages.append(message) + + def on_field_name(self, data: bytes, start: int, end: int) -> None: + message = (FormMessage.FIELD_NAME, data[start:end]) + self.messages.append(message) + + def on_field_data(self, data: bytes, start: int, end: int) -> None: + message = (FormMessage.FIELD_DATA, data[start:end]) + self.messages.append(message) + + def on_field_end(self) -> None: + message = (FormMessage.FIELD_END, b"") + self.messages.append(message) + + def on_end(self) -> None: + message = (FormMessage.END, b"") + self.messages.append(message) + + async def parse(self) -> FormData: + # Callbacks dictionary. + callbacks = { + "on_field_start": self.on_field_start, + "on_field_name": self.on_field_name, + "on_field_data": self.on_field_data, + "on_field_end": self.on_field_end, + "on_end": self.on_end, + } + + # Create the parser. + parser = multipart.QuerystringParser(callbacks) + field_name = b"" + field_value = b"" + + items: typing.List[typing.Tuple[str, typing.Union[str, UploadFile]]] = [] + + # Feed the parser with data from the request. + async for chunk in self.stream: + if chunk: + parser.write(chunk) + else: + parser.finalize() + messages = list(self.messages) + self.messages.clear() + for message_type, message_bytes in messages: + if message_type == FormMessage.FIELD_START: + field_name = b"" + field_value = b"" + elif message_type == FormMessage.FIELD_NAME: + field_name += message_bytes + elif message_type == FormMessage.FIELD_DATA: + field_value += message_bytes + elif message_type == FormMessage.FIELD_END: + name = unquote_plus(field_name.decode("latin-1")) + value = unquote_plus(field_value.decode("latin-1")) + items.append((name, value)) + + return FormData(items) + + +class MultiPartParser: + def __init__( + self, headers: Headers, stream: typing.AsyncGenerator[bytes, None] + ) -> None: + assert ( + multipart is not None + ), "The `python-multipart` library must be installed to use form parsing." + self.headers = headers + self.stream = stream + self.messages: typing.List[typing.Tuple[MultiPartMessage, bytes]] = [] + + def on_part_begin(self) -> None: + message = (MultiPartMessage.PART_BEGIN, b"") + self.messages.append(message) + + def on_part_data(self, data: bytes, start: int, end: int) -> None: + message = (MultiPartMessage.PART_DATA, data[start:end]) + self.messages.append(message) + + def on_part_end(self) -> None: + message = (MultiPartMessage.PART_END, b"") + self.messages.append(message) + + def on_header_field(self, data: bytes, start: int, end: int) -> None: + message = (MultiPartMessage.HEADER_FIELD, data[start:end]) + self.messages.append(message) + + def on_header_value(self, data: bytes, start: int, end: int) -> None: + message = (MultiPartMessage.HEADER_VALUE, data[start:end]) + self.messages.append(message) + + def on_header_end(self) -> None: + message = (MultiPartMessage.HEADER_END, b"") + self.messages.append(message) + + def on_headers_finished(self) -> None: + message = (MultiPartMessage.HEADERS_FINISHED, b"") + self.messages.append(message) + + def on_end(self) -> None: + message = (MultiPartMessage.END, b"") + self.messages.append(message) + + async def parse(self) -> FormData: + # Parse the Content-Type header to get the multipart boundary. + content_type, params = parse_options_header(self.headers["Content-Type"]) + charset = params.get(b"charset", "utf-8") + if type(charset) == bytes: + charset = charset.decode("latin-1") + boundary = params[b"boundary"] + + # Callbacks dictionary. + callbacks = { + "on_part_begin": self.on_part_begin, + "on_part_data": self.on_part_data, + "on_part_end": self.on_part_end, + "on_header_field": self.on_header_field, + "on_header_value": self.on_header_value, + "on_header_end": self.on_header_end, + "on_headers_finished": self.on_headers_finished, + "on_end": self.on_end, + } + + # Create the parser. + parser = multipart.MultipartParser(boundary, callbacks) + header_field = b"" + header_value = b"" + content_disposition = None + content_type = b"" + field_name = "" + data = b"" + file: typing.Optional[UploadFile] = None + + items: typing.List[typing.Tuple[str, typing.Union[str, UploadFile]]] = [] + item_headers: typing.List[typing.Tuple[bytes, bytes]] = [] + + # Feed the parser with data from the request. + async for chunk in self.stream: + parser.write(chunk) + messages = list(self.messages) + self.messages.clear() + for message_type, message_bytes in messages: + if message_type == MultiPartMessage.PART_BEGIN: + content_disposition = None + content_type = b"" + data = b"" + item_headers = [] + elif message_type == MultiPartMessage.HEADER_FIELD: + header_field += message_bytes + elif message_type == MultiPartMessage.HEADER_VALUE: + header_value += message_bytes + elif message_type == MultiPartMessage.HEADER_END: + field = header_field.lower() + if field == b"content-disposition": + content_disposition = header_value + elif field == b"content-type": + content_type = header_value + item_headers.append((field, header_value)) + header_field = b"" + header_value = b"" + elif message_type == MultiPartMessage.HEADERS_FINISHED: + disposition, options = parse_options_header(content_disposition) + field_name = _user_safe_decode(options[b"name"], charset) + if b"filename" in options: + filename = _user_safe_decode(options[b"filename"], charset) + file = UploadFile( + filename=filename, + content_type=content_type.decode("latin-1"), + headers=Headers(raw=item_headers), + ) + else: + file = None + elif message_type == MultiPartMessage.PART_DATA: + if file is None: + data += message_bytes + else: + await file.write(message_bytes) + elif message_type == MultiPartMessage.PART_END: + if file is None: + items.append((field_name, _user_safe_decode(data, charset))) + else: + await file.seek(0) + items.append((field_name, file)) + + parser.finalize() + return FormData(items) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/__init__.py new file mode 100644 index 00000000..5ac5b96c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/__init__.py @@ -0,0 +1,17 @@ +import typing + + +class Middleware: + def __init__(self, cls: type, **options: typing.Any) -> None: + self.cls = cls + self.options = options + + def __iter__(self) -> typing.Iterator: + as_tuple = (self.cls, self.options) + return iter(as_tuple) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + option_strings = [f"{key}={value!r}" for key, value in self.options.items()] + args_repr = ", ".join([self.cls.__name__] + option_strings) + return f"{class_name}({args_repr})" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/authentication.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/authentication.py new file mode 100644 index 00000000..76e4a246 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/authentication.py @@ -0,0 +1,52 @@ +import typing + +from starlette.authentication import ( + AuthCredentials, + AuthenticationBackend, + AuthenticationError, + UnauthenticatedUser, +) +from starlette.requests import HTTPConnection +from starlette.responses import PlainTextResponse, Response +from starlette.types import ASGIApp, Receive, Scope, Send + + +class AuthenticationMiddleware: + def __init__( + self, + app: ASGIApp, + backend: AuthenticationBackend, + on_error: typing.Optional[ + typing.Callable[[HTTPConnection, AuthenticationError], Response] + ] = None, + ) -> None: + self.app = app + self.backend = backend + self.on_error: typing.Callable[ + [HTTPConnection, AuthenticationError], Response + ] = (on_error if on_error is not None else self.default_on_error) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] not in ["http", "websocket"]: + await self.app(scope, receive, send) + return + + conn = HTTPConnection(scope) + try: + auth_result = await self.backend.authenticate(conn) + except AuthenticationError as exc: + response = self.on_error(conn, exc) + if scope["type"] == "websocket": + await send({"type": "websocket.close", "code": 1000}) + else: + await response(scope, receive, send) + return + + if auth_result is None: + auth_result = AuthCredentials(), UnauthenticatedUser() + scope["auth"], scope["user"] = auth_result + await self.app(scope, receive, send) + + @staticmethod + def default_on_error(conn: HTTPConnection, exc: Exception) -> Response: + return PlainTextResponse(str(exc), status_code=400) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/base.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/base.py new file mode 100644 index 00000000..ca9deb7d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/base.py @@ -0,0 +1,75 @@ +import typing + +import anyio + +from starlette.requests import Request +from starlette.responses import Response, StreamingResponse +from starlette.types import ASGIApp, Receive, Scope, Send + +RequestResponseEndpoint = typing.Callable[[Request], typing.Awaitable[Response]] +DispatchFunction = typing.Callable[ + [Request, RequestResponseEndpoint], typing.Awaitable[Response] +] + + +class BaseHTTPMiddleware: + def __init__( + self, app: ASGIApp, dispatch: typing.Optional[DispatchFunction] = None + ) -> None: + self.app = app + self.dispatch_func = self.dispatch if dispatch is None else dispatch + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + async def call_next(request: Request) -> Response: + app_exc: typing.Optional[Exception] = None + send_stream, recv_stream = anyio.create_memory_object_stream() + + async def coro() -> None: + nonlocal app_exc + + async with send_stream: + try: + await self.app(scope, request.receive, send_stream.send) + except Exception as exc: + app_exc = exc + + task_group.start_soon(coro) + + try: + message = await recv_stream.receive() + except anyio.EndOfStream: + if app_exc is not None: + raise app_exc + raise RuntimeError("No response returned.") + + assert message["type"] == "http.response.start" + + async def body_stream() -> typing.AsyncGenerator[bytes, None]: + async with recv_stream: + async for message in recv_stream: + assert message["type"] == "http.response.body" + yield message.get("body", b"") + + if app_exc is not None: + raise app_exc + + response = StreamingResponse( + status_code=message["status"], content=body_stream() + ) + response.raw_headers = message["headers"] + return response + + async with anyio.create_task_group() as task_group: + request = Request(scope, receive=receive) + response = await self.dispatch_func(request, call_next) + await response(scope, receive, send) + task_group.cancel_scope.cancel() + + async def dispatch( + self, request: Request, call_next: RequestResponseEndpoint + ) -> Response: + raise NotImplementedError() # pragma: no cover diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/cors.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/cors.py new file mode 100644 index 00000000..b36d155f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/cors.py @@ -0,0 +1,177 @@ +import functools +import re +import typing + +from starlette.datastructures import Headers, MutableHeaders +from starlette.responses import PlainTextResponse, Response +from starlette.types import ASGIApp, Message, Receive, Scope, Send + +ALL_METHODS = ("DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT") +SAFELISTED_HEADERS = {"Accept", "Accept-Language", "Content-Language", "Content-Type"} + + +class CORSMiddleware: + def __init__( + self, + app: ASGIApp, + allow_origins: typing.Sequence[str] = (), + allow_methods: typing.Sequence[str] = ("GET",), + allow_headers: typing.Sequence[str] = (), + allow_credentials: bool = False, + allow_origin_regex: typing.Optional[str] = None, + expose_headers: typing.Sequence[str] = (), + max_age: int = 600, + ) -> None: + + if "*" in allow_methods: + allow_methods = ALL_METHODS + + compiled_allow_origin_regex = None + if allow_origin_regex is not None: + compiled_allow_origin_regex = re.compile(allow_origin_regex) + + allow_all_origins = "*" in allow_origins + allow_all_headers = "*" in allow_headers + preflight_explicit_allow_origin = not allow_all_origins or allow_credentials + + simple_headers = {} + if allow_all_origins: + simple_headers["Access-Control-Allow-Origin"] = "*" + if allow_credentials: + simple_headers["Access-Control-Allow-Credentials"] = "true" + if expose_headers: + simple_headers["Access-Control-Expose-Headers"] = ", ".join(expose_headers) + + preflight_headers = {} + if preflight_explicit_allow_origin: + # The origin value will be set in preflight_response() if it is allowed. + preflight_headers["Vary"] = "Origin" + else: + preflight_headers["Access-Control-Allow-Origin"] = "*" + preflight_headers.update( + { + "Access-Control-Allow-Methods": ", ".join(allow_methods), + "Access-Control-Max-Age": str(max_age), + } + ) + allow_headers = sorted(SAFELISTED_HEADERS | set(allow_headers)) + if allow_headers and not allow_all_headers: + preflight_headers["Access-Control-Allow-Headers"] = ", ".join(allow_headers) + if allow_credentials: + preflight_headers["Access-Control-Allow-Credentials"] = "true" + + self.app = app + self.allow_origins = allow_origins + self.allow_methods = allow_methods + self.allow_headers = [h.lower() for h in allow_headers] + self.allow_all_origins = allow_all_origins + self.allow_all_headers = allow_all_headers + self.preflight_explicit_allow_origin = preflight_explicit_allow_origin + self.allow_origin_regex = compiled_allow_origin_regex + self.simple_headers = simple_headers + self.preflight_headers = preflight_headers + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": # pragma: no cover + await self.app(scope, receive, send) + return + + method = scope["method"] + headers = Headers(scope=scope) + origin = headers.get("origin") + + if origin is None: + await self.app(scope, receive, send) + return + + if method == "OPTIONS" and "access-control-request-method" in headers: + response = self.preflight_response(request_headers=headers) + await response(scope, receive, send) + return + + await self.simple_response(scope, receive, send, request_headers=headers) + + def is_allowed_origin(self, origin: str) -> bool: + if self.allow_all_origins: + return True + + if self.allow_origin_regex is not None and self.allow_origin_regex.fullmatch( + origin + ): + return True + + return origin in self.allow_origins + + def preflight_response(self, request_headers: Headers) -> Response: + requested_origin = request_headers["origin"] + requested_method = request_headers["access-control-request-method"] + requested_headers = request_headers.get("access-control-request-headers") + + headers = dict(self.preflight_headers) + failures = [] + + if self.is_allowed_origin(origin=requested_origin): + if self.preflight_explicit_allow_origin: + # The "else" case is already accounted for in self.preflight_headers + # and the value would be "*". + headers["Access-Control-Allow-Origin"] = requested_origin + else: + failures.append("origin") + + if requested_method not in self.allow_methods: + failures.append("method") + + # If we allow all headers, then we have to mirror back any requested + # headers in the response. + if self.allow_all_headers and requested_headers is not None: + headers["Access-Control-Allow-Headers"] = requested_headers + elif requested_headers is not None: + for header in [h.lower() for h in requested_headers.split(",")]: + if header.strip() not in self.allow_headers: + failures.append("headers") + break + + # We don't strictly need to use 400 responses here, since its up to + # the browser to enforce the CORS policy, but its more informative + # if we do. + if failures: + failure_text = "Disallowed CORS " + ", ".join(failures) + return PlainTextResponse(failure_text, status_code=400, headers=headers) + + return PlainTextResponse("OK", status_code=200, headers=headers) + + async def simple_response( + self, scope: Scope, receive: Receive, send: Send, request_headers: Headers + ) -> None: + send = functools.partial(self.send, send=send, request_headers=request_headers) + await self.app(scope, receive, send) + + async def send( + self, message: Message, send: Send, request_headers: Headers + ) -> None: + if message["type"] != "http.response.start": + await send(message) + return + + message.setdefault("headers", []) + headers = MutableHeaders(scope=message) + headers.update(self.simple_headers) + origin = request_headers["Origin"] + has_cookie = "cookie" in request_headers + + # If request includes any cookie headers, then we must respond + # with the specific origin instead of '*'. + if self.allow_all_origins and has_cookie: + self.allow_explicit_origin(headers, origin) + + # If we only allow specific origins, then we have to mirror back + # the Origin header in the response. + elif not self.allow_all_origins and self.is_allowed_origin(origin=origin): + self.allow_explicit_origin(headers, origin) + + await send(message) + + @staticmethod + def allow_explicit_origin(headers: MutableHeaders, origin: str) -> None: + headers["Access-Control-Allow-Origin"] = origin + headers.add_vary_header("Origin") diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/errors.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/errors.py new file mode 100644 index 00000000..acb1930f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/errors.py @@ -0,0 +1,254 @@ +import asyncio +import html +import inspect +import traceback +import typing + +from starlette.concurrency import run_in_threadpool +from starlette.requests import Request +from starlette.responses import HTMLResponse, PlainTextResponse, Response +from starlette.types import ASGIApp, Message, Receive, Scope, Send + +STYLES = """ +p { + color: #211c1c; +} +.traceback-container { + border: 1px solid #038BB8; +} +.traceback-title { + background-color: #038BB8; + color: lemonchiffon; + padding: 12px; + font-size: 20px; + margin-top: 0px; +} +.frame-line { + padding-left: 10px; + font-family: monospace; +} +.frame-filename { + font-family: monospace; +} +.center-line { + background-color: #038BB8; + color: #f9f6e1; + padding: 5px 0px 5px 5px; +} +.lineno { + margin-right: 5px; +} +.frame-title { + font-weight: unset; + padding: 10px 10px 10px 10px; + background-color: #E4F4FD; + margin-right: 10px; + color: #191f21; + font-size: 17px; + border: 1px solid #c7dce8; +} +.collapse-btn { + float: right; + padding: 0px 5px 1px 5px; + border: solid 1px #96aebb; + cursor: pointer; +} +.collapsed { + display: none; +} +.source-code { + font-family: courier; + font-size: small; + padding-bottom: 10px; +} +""" + +JS = """ + +""" + +TEMPLATE = """ + + + + Starlette Debugger + + +

      500 Server Error

      +

      {error}

      +
      +

      Traceback

      +
      {exc_html}
      +
      + {js} + + +""" + +FRAME_TEMPLATE = """ +
      +

      File {frame_filename}, + line {frame_lineno}, + in {frame_name} + {collapse_button} +

      +
      {code_context}
      +
      +""" # noqa: E501 + +LINE = """ +

      +{lineno}. {line}

      +""" + +CENTER_LINE = """ +

      +{lineno}. {line}

      +""" + + +class ServerErrorMiddleware: + """ + Handles returning 500 responses when a server error occurs. + + If 'debug' is set, then traceback responses will be returned, + otherwise the designated 'handler' will be called. + + This middleware class should generally be used to wrap *everything* + else up, so that unhandled exceptions anywhere in the stack + always result in an appropriate 500 response. + """ + + def __init__( + self, + app: ASGIApp, + handler: typing.Optional[typing.Callable] = None, + debug: bool = False, + ) -> None: + self.app = app + self.handler = handler + self.debug = debug + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + response_started = False + + async def _send(message: Message) -> None: + nonlocal response_started, send + + if message["type"] == "http.response.start": + response_started = True + await send(message) + + try: + await self.app(scope, receive, _send) + except Exception as exc: + request = Request(scope) + if self.debug: + # In debug mode, return traceback responses. + response = self.debug_response(request, exc) + elif self.handler is None: + # Use our default 500 error handler. + response = self.error_response(request, exc) + else: + # Use an installed 500 error handler. + if asyncio.iscoroutinefunction(self.handler): + response = await self.handler(request, exc) + else: + response = await run_in_threadpool(self.handler, request, exc) + + if not response_started: + await response(scope, receive, send) + + # We always continue to raise the exception. + # This allows servers to log the error, or allows test clients + # to optionally raise the error within the test case. + raise exc + + def format_line( + self, index: int, line: str, frame_lineno: int, frame_index: int + ) -> str: + values = { + # HTML escape - line could contain < or > + "line": html.escape(line).replace(" ", " "), + "lineno": (frame_lineno - frame_index) + index, + } + + if index != frame_index: + return LINE.format(**values) + return CENTER_LINE.format(**values) + + def generate_frame_html(self, frame: inspect.FrameInfo, is_collapsed: bool) -> str: + code_context = "".join( + self.format_line(index, line, frame.lineno, frame.index) # type: ignore + for index, line in enumerate(frame.code_context or []) + ) + + values = { + # HTML escape - filename could contain < or >, especially if it's a virtual + # file e.g. in the REPL + "frame_filename": html.escape(frame.filename), + "frame_lineno": frame.lineno, + # HTML escape - if you try very hard it's possible to name a function with < + # or > + "frame_name": html.escape(frame.function), + "code_context": code_context, + "collapsed": "collapsed" if is_collapsed else "", + "collapse_button": "+" if is_collapsed else "‒", + } + return FRAME_TEMPLATE.format(**values) + + def generate_html(self, exc: Exception, limit: int = 7) -> str: + traceback_obj = traceback.TracebackException.from_exception( + exc, capture_locals=True + ) + + exc_html = "" + is_collapsed = False + exc_traceback = exc.__traceback__ + if exc_traceback is not None: + frames = inspect.getinnerframes(exc_traceback, limit) + for frame in reversed(frames): + exc_html += self.generate_frame_html(frame, is_collapsed) + is_collapsed = True + + # escape error class and text + error = ( + f"{html.escape(traceback_obj.exc_type.__name__)}: " + f"{html.escape(str(traceback_obj))}" + ) + + return TEMPLATE.format(styles=STYLES, js=JS, error=error, exc_html=exc_html) + + def generate_plain_text(self, exc: Exception) -> str: + return "".join(traceback.format_exception(type(exc), exc, exc.__traceback__)) + + def debug_response(self, request: Request, exc: Exception) -> Response: + accept = request.headers.get("accept", "") + + if "text/html" in accept: + content = self.generate_html(exc) + return HTMLResponse(content, status_code=500) + content = self.generate_plain_text(exc) + return PlainTextResponse(content, status_code=500) + + def error_response(self, request: Request, exc: Exception) -> Response: + return PlainTextResponse("Internal Server Error", status_code=500) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/gzip.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/gzip.py new file mode 100644 index 00000000..9d69ee7c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/gzip.py @@ -0,0 +1,105 @@ +import gzip +import io +import typing + +from starlette.datastructures import Headers, MutableHeaders +from starlette.types import ASGIApp, Message, Receive, Scope, Send + + +class GZipMiddleware: + def __init__( + self, app: ASGIApp, minimum_size: int = 500, compresslevel: int = 9 + ) -> None: + self.app = app + self.minimum_size = minimum_size + self.compresslevel = compresslevel + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] == "http": + headers = Headers(scope=scope) + if "gzip" in headers.get("Accept-Encoding", ""): + responder = GZipResponder( + self.app, self.minimum_size, compresslevel=self.compresslevel + ) + await responder(scope, receive, send) + return + await self.app(scope, receive, send) + + +class GZipResponder: + def __init__(self, app: ASGIApp, minimum_size: int, compresslevel: int = 9) -> None: + self.app = app + self.minimum_size = minimum_size + self.send: Send = unattached_send + self.initial_message: Message = {} + self.started = False + self.gzip_buffer = io.BytesIO() + self.gzip_file = gzip.GzipFile( + mode="wb", fileobj=self.gzip_buffer, compresslevel=compresslevel + ) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + self.send = send + await self.app(scope, receive, self.send_with_gzip) + + async def send_with_gzip(self, message: Message) -> None: + message_type = message["type"] + if message_type == "http.response.start": + # Don't send the initial message until we've determined how to + # modify the outgoing headers correctly. + self.initial_message = message + elif message_type == "http.response.body" and not self.started: + self.started = True + body = message.get("body", b"") + more_body = message.get("more_body", False) + if len(body) < self.minimum_size and not more_body: + # Don't apply GZip to small outgoing responses. + await self.send(self.initial_message) + await self.send(message) + elif not more_body: + # Standard GZip response. + self.gzip_file.write(body) + self.gzip_file.close() + body = self.gzip_buffer.getvalue() + + headers = MutableHeaders(raw=self.initial_message["headers"]) + headers["Content-Encoding"] = "gzip" + headers["Content-Length"] = str(len(body)) + headers.add_vary_header("Accept-Encoding") + message["body"] = body + + await self.send(self.initial_message) + await self.send(message) + else: + # Initial body in streaming GZip response. + headers = MutableHeaders(raw=self.initial_message["headers"]) + headers["Content-Encoding"] = "gzip" + headers.add_vary_header("Accept-Encoding") + del headers["Content-Length"] + + self.gzip_file.write(body) + message["body"] = self.gzip_buffer.getvalue() + self.gzip_buffer.seek(0) + self.gzip_buffer.truncate() + + await self.send(self.initial_message) + await self.send(message) + + elif message_type == "http.response.body": + # Remaining body in streaming GZip response. + body = message.get("body", b"") + more_body = message.get("more_body", False) + + self.gzip_file.write(body) + if not more_body: + self.gzip_file.close() + + message["body"] = self.gzip_buffer.getvalue() + self.gzip_buffer.seek(0) + self.gzip_buffer.truncate() + + await self.send(message) + + +async def unattached_send(message: Message) -> typing.NoReturn: + raise RuntimeError("send awaitable not set") # pragma: no cover diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/httpsredirect.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/httpsredirect.py new file mode 100644 index 00000000..a8359067 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/httpsredirect.py @@ -0,0 +1,19 @@ +from starlette.datastructures import URL +from starlette.responses import RedirectResponse +from starlette.types import ASGIApp, Receive, Scope, Send + + +class HTTPSRedirectMiddleware: + def __init__(self, app: ASGIApp) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] in ("http", "websocket") and scope["scheme"] in ("http", "ws"): + url = URL(scope=scope) + redirect_scheme = {"http": "https", "ws": "wss"}[url.scheme] + netloc = url.hostname if url.port in (80, 443) else url.netloc + url = url.replace(scheme=redirect_scheme, netloc=netloc) + response = RedirectResponse(url, status_code=307) + await response(scope, receive, send) + else: + await self.app(scope, receive, send) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/sessions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/sessions.py new file mode 100644 index 00000000..597de38a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/sessions.py @@ -0,0 +1,80 @@ +import json +import typing +from base64 import b64decode, b64encode + +import itsdangerous +from itsdangerous.exc import BadSignature + +from starlette.datastructures import MutableHeaders, Secret +from starlette.requests import HTTPConnection +from starlette.types import ASGIApp, Message, Receive, Scope, Send + + +class SessionMiddleware: + def __init__( + self, + app: ASGIApp, + secret_key: typing.Union[str, Secret], + session_cookie: str = "session", + max_age: typing.Optional[int] = 14 * 24 * 60 * 60, # 14 days, in seconds + path: str = "/", + same_site: str = "lax", + https_only: bool = False, + ) -> None: + self.app = app + self.signer = itsdangerous.TimestampSigner(str(secret_key)) + self.session_cookie = session_cookie + self.max_age = max_age + self.path = path + self.security_flags = "httponly; samesite=" + same_site + if https_only: # Secure flag can be used with HTTPS only + self.security_flags += "; secure" + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] not in ("http", "websocket"): # pragma: no cover + await self.app(scope, receive, send) + return + + connection = HTTPConnection(scope) + initial_session_was_empty = True + + if self.session_cookie in connection.cookies: + data = connection.cookies[self.session_cookie].encode("utf-8") + try: + data = self.signer.unsign(data, max_age=self.max_age) + scope["session"] = json.loads(b64decode(data)) + initial_session_was_empty = False + except BadSignature: + scope["session"] = {} + else: + scope["session"] = {} + + async def send_wrapper(message: Message) -> None: + if message["type"] == "http.response.start": + if scope["session"]: + # We have session data to persist. + data = b64encode(json.dumps(scope["session"]).encode("utf-8")) + data = self.signer.sign(data) + headers = MutableHeaders(scope=message) + header_value = "{session_cookie}={data}; path={path}; {max_age}{security_flags}".format( # noqa E501 + session_cookie=self.session_cookie, + data=data.decode("utf-8"), + path=self.path, + max_age=f"Max-Age={self.max_age}; " if self.max_age else "", + security_flags=self.security_flags, + ) + headers.append("Set-Cookie", header_value) + elif not initial_session_was_empty: + # The session has been cleared. + headers = MutableHeaders(scope=message) + header_value = "{session_cookie}={data}; path={path}; {expires}{security_flags}".format( # noqa E501 + session_cookie=self.session_cookie, + data="null", + path=self.path, + expires="expires=Thu, 01 Jan 1970 00:00:00 GMT; ", + security_flags=self.security_flags, + ) + headers.append("Set-Cookie", header_value) + await send(message) + + await self.app(scope, receive, send_wrapper) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/trustedhost.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/trustedhost.py new file mode 100644 index 00000000..e84e6876 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/trustedhost.py @@ -0,0 +1,60 @@ +import typing + +from starlette.datastructures import URL, Headers +from starlette.responses import PlainTextResponse, RedirectResponse, Response +from starlette.types import ASGIApp, Receive, Scope, Send + +ENFORCE_DOMAIN_WILDCARD = "Domain wildcard patterns must be like '*.example.com'." + + +class TrustedHostMiddleware: + def __init__( + self, + app: ASGIApp, + allowed_hosts: typing.Optional[typing.Sequence[str]] = None, + www_redirect: bool = True, + ) -> None: + if allowed_hosts is None: + allowed_hosts = ["*"] + + for pattern in allowed_hosts: + assert "*" not in pattern[1:], ENFORCE_DOMAIN_WILDCARD + if pattern.startswith("*") and pattern != "*": + assert pattern.startswith("*."), ENFORCE_DOMAIN_WILDCARD + self.app = app + self.allowed_hosts = list(allowed_hosts) + self.allow_any = "*" in allowed_hosts + self.www_redirect = www_redirect + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.allow_any or scope["type"] not in ( + "http", + "websocket", + ): # pragma: no cover + await self.app(scope, receive, send) + return + + headers = Headers(scope=scope) + host = headers.get("host", "").split(":")[0] + is_valid_host = False + found_www_redirect = False + for pattern in self.allowed_hosts: + if host == pattern or ( + pattern.startswith("*") and host.endswith(pattern[1:]) + ): + is_valid_host = True + break + elif "www." + host == pattern: + found_www_redirect = True + + if is_valid_host: + await self.app(scope, receive, send) + else: + response: Response + if found_www_redirect and self.www_redirect: + url = URL(scope=scope) + redirect_url = url.replace(netloc="www." + url.netloc) + response = RedirectResponse(url=str(redirect_url)) + else: + response = PlainTextResponse("Invalid host header", status_code=400) + await response(scope, receive, send) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/wsgi.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/wsgi.py new file mode 100644 index 00000000..9dbd0652 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/middleware/wsgi.py @@ -0,0 +1,140 @@ +import io +import math +import sys +import typing +import warnings + +import anyio + +from starlette.types import Receive, Scope, Send + +warnings.warn( + "starlette.middleware.wsgi is deprecated and will be removed in a future release. " + "Please refer to https://github.com/abersheeran/a2wsgi as a replacement.", + DeprecationWarning, +) + + +def build_environ(scope: Scope, body: bytes) -> dict: + """ + Builds a scope and request body into a WSGI environ object. + """ + environ = { + "REQUEST_METHOD": scope["method"], + "SCRIPT_NAME": scope.get("root_path", "").encode("utf8").decode("latin1"), + "PATH_INFO": scope["path"].encode("utf8").decode("latin1"), + "QUERY_STRING": scope["query_string"].decode("ascii"), + "SERVER_PROTOCOL": f"HTTP/{scope['http_version']}", + "wsgi.version": (1, 0), + "wsgi.url_scheme": scope.get("scheme", "http"), + "wsgi.input": io.BytesIO(body), + "wsgi.errors": sys.stdout, + "wsgi.multithread": True, + "wsgi.multiprocess": True, + "wsgi.run_once": False, + } + + # Get server name and port - required in WSGI, not in ASGI + server = scope.get("server") or ("localhost", 80) + environ["SERVER_NAME"] = server[0] + environ["SERVER_PORT"] = server[1] + + # Get client IP address + if scope.get("client"): + environ["REMOTE_ADDR"] = scope["client"][0] + + # Go through headers and make them into environ entries + for name, value in scope.get("headers", []): + name = name.decode("latin1") + if name == "content-length": + corrected_name = "CONTENT_LENGTH" + elif name == "content-type": + corrected_name = "CONTENT_TYPE" + else: + corrected_name = f"HTTP_{name}".upper().replace("-", "_") + # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in + # case + value = value.decode("latin1") + if corrected_name in environ: + value = environ[corrected_name] + "," + value + environ[corrected_name] = value + return environ + + +class WSGIMiddleware: + def __init__(self, app: typing.Callable) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] == "http" + responder = WSGIResponder(self.app, scope) + await responder(receive, send) + + +class WSGIResponder: + def __init__(self, app: typing.Callable, scope: Scope) -> None: + self.app = app + self.scope = scope + self.status = None + self.response_headers = None + self.stream_send, self.stream_receive = anyio.create_memory_object_stream( + math.inf + ) + self.response_started = False + self.exc_info: typing.Any = None + + async def __call__(self, receive: Receive, send: Send) -> None: + body = b"" + more_body = True + while more_body: + message = await receive() + body += message.get("body", b"") + more_body = message.get("more_body", False) + environ = build_environ(self.scope, body) + + async with anyio.create_task_group() as task_group: + task_group.start_soon(self.sender, send) + async with self.stream_send: + await anyio.to_thread.run_sync(self.wsgi, environ, self.start_response) + if self.exc_info is not None: + raise self.exc_info[0].with_traceback(self.exc_info[1], self.exc_info[2]) + + async def sender(self, send: Send) -> None: + async with self.stream_receive: + async for message in self.stream_receive: + await send(message) + + def start_response( + self, + status: str, + response_headers: typing.List[typing.Tuple[str, str]], + exc_info: typing.Any = None, + ) -> None: + self.exc_info = exc_info + if not self.response_started: + self.response_started = True + status_code_string, _ = status.split(" ", 1) + status_code = int(status_code_string) + headers = [ + (name.strip().encode("ascii").lower(), value.strip().encode("ascii")) + for name, value in response_headers + ] + anyio.from_thread.run( + self.stream_send.send, + { + "type": "http.response.start", + "status": status_code, + "headers": headers, + }, + ) + + def wsgi(self, environ: dict, start_response: typing.Callable) -> None: + for chunk in self.app(environ, start_response): + anyio.from_thread.run( + self.stream_send.send, + {"type": "http.response.body", "body": chunk, "more_body": True}, + ) + + anyio.from_thread.run( + self.stream_send.send, {"type": "http.response.body", "body": b""} + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/requests.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/requests.py new file mode 100644 index 00000000..c738ebaa --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/requests.py @@ -0,0 +1,290 @@ +import json +import typing +from collections.abc import Mapping +from http import cookies as http_cookies + +import anyio + +from starlette.datastructures import URL, Address, FormData, Headers, QueryParams, State +from starlette.formparsers import FormParser, MultiPartParser +from starlette.types import Message, Receive, Scope, Send + +try: + from multipart.multipart import parse_options_header +except ImportError: # pragma: nocover + parse_options_header = None + + +if typing.TYPE_CHECKING: + from starlette.routing import Router + + +SERVER_PUSH_HEADERS_TO_COPY = { + "accept", + "accept-encoding", + "accept-language", + "cache-control", + "user-agent", +} + + +def cookie_parser(cookie_string: str) -> typing.Dict[str, str]: + """ + This function parses a ``Cookie`` HTTP header into a dict of key/value pairs. + + It attempts to mimic browser cookie parsing behavior: browsers and web servers + frequently disregard the spec (RFC 6265) when setting and reading cookies, + so we attempt to suit the common scenarios here. + + This function has been adapted from Django 3.1.0. + Note: we are explicitly _NOT_ using `SimpleCookie.load` because it is based + on an outdated spec and will fail on lots of input we want to support + """ + cookie_dict: typing.Dict[str, str] = {} + for chunk in cookie_string.split(";"): + if "=" in chunk: + key, val = chunk.split("=", 1) + else: + # Assume an empty name per + # https://bugzilla.mozilla.org/show_bug.cgi?id=169091 + key, val = "", chunk + key, val = key.strip(), val.strip() + if key or val: + # unquote using Python's algorithm. + cookie_dict[key] = http_cookies._unquote(val) + return cookie_dict + + +class ClientDisconnect(Exception): + pass + + +class HTTPConnection(Mapping): + """ + A base class for incoming HTTP connections, that is used to provide + any functionality that is common to both `Request` and `WebSocket`. + """ + + def __init__(self, scope: Scope, receive: typing.Optional[Receive] = None) -> None: + assert scope["type"] in ("http", "websocket") + self.scope = scope + + def __getitem__(self, key: str) -> typing.Any: + return self.scope[key] + + def __iter__(self) -> typing.Iterator[str]: + return iter(self.scope) + + def __len__(self) -> int: + return len(self.scope) + + # Don't use the `abc.Mapping.__eq__` implementation. + # Connection instances should never be considered equal + # unless `self is other`. + __eq__ = object.__eq__ + __hash__ = object.__hash__ + + @property + def app(self) -> typing.Any: + return self.scope["app"] + + @property + def url(self) -> URL: + if not hasattr(self, "_url"): + self._url = URL(scope=self.scope) + return self._url + + @property + def base_url(self) -> URL: + if not hasattr(self, "_base_url"): + base_url_scope = dict(self.scope) + base_url_scope["path"] = "/" + base_url_scope["query_string"] = b"" + base_url_scope["root_path"] = base_url_scope.get( + "app_root_path", base_url_scope.get("root_path", "") + ) + self._base_url = URL(scope=base_url_scope) + return self._base_url + + @property + def headers(self) -> Headers: + if not hasattr(self, "_headers"): + self._headers = Headers(scope=self.scope) + return self._headers + + @property + def query_params(self) -> QueryParams: + if not hasattr(self, "_query_params"): + self._query_params = QueryParams(self.scope["query_string"]) + return self._query_params + + @property + def path_params(self) -> typing.Dict[str, typing.Any]: + return self.scope.get("path_params", {}) + + @property + def cookies(self) -> typing.Dict[str, str]: + if not hasattr(self, "_cookies"): + cookies: typing.Dict[str, str] = {} + cookie_header = self.headers.get("cookie") + + if cookie_header: + cookies = cookie_parser(cookie_header) + self._cookies = cookies + return self._cookies + + @property + def client(self) -> typing.Optional[Address]: + # client is a 2 item tuple of (host, port), None or missing + host_port = self.scope.get("client") + if host_port is not None: + return Address(*host_port) + return None + + @property + def session(self) -> dict: + assert ( + "session" in self.scope + ), "SessionMiddleware must be installed to access request.session" + return self.scope["session"] + + @property + def auth(self) -> typing.Any: + assert ( + "auth" in self.scope + ), "AuthenticationMiddleware must be installed to access request.auth" + return self.scope["auth"] + + @property + def user(self) -> typing.Any: + assert ( + "user" in self.scope + ), "AuthenticationMiddleware must be installed to access request.user" + return self.scope["user"] + + @property + def state(self) -> State: + if not hasattr(self, "_state"): + # Ensure 'state' has an empty dict if it's not already populated. + self.scope.setdefault("state", {}) + # Create a state instance with a reference to the dict in which it should + # store info + self._state = State(self.scope["state"]) + return self._state + + def url_for(self, name: str, **path_params: typing.Any) -> str: + router: Router = self.scope["router"] + url_path = router.url_path_for(name, **path_params) + return url_path.make_absolute_url(base_url=self.base_url) + + +async def empty_receive() -> typing.NoReturn: + raise RuntimeError("Receive channel has not been made available") + + +async def empty_send(message: Message) -> typing.NoReturn: + raise RuntimeError("Send channel has not been made available") + + +class Request(HTTPConnection): + def __init__( + self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send + ): + super().__init__(scope) + assert scope["type"] == "http" + self._receive = receive + self._send = send + self._stream_consumed = False + self._is_disconnected = False + + @property + def method(self) -> str: + return self.scope["method"] + + @property + def receive(self) -> Receive: + return self._receive + + async def stream(self) -> typing.AsyncGenerator[bytes, None]: + if hasattr(self, "_body"): + yield self._body + yield b"" + return + + if self._stream_consumed: + raise RuntimeError("Stream consumed") + + self._stream_consumed = True + while True: + message = await self._receive() + if message["type"] == "http.request": + body = message.get("body", b"") + if body: + yield body + if not message.get("more_body", False): + break + elif message["type"] == "http.disconnect": + self._is_disconnected = True + raise ClientDisconnect() + yield b"" + + async def body(self) -> bytes: + if not hasattr(self, "_body"): + chunks = [] + async for chunk in self.stream(): + chunks.append(chunk) + self._body = b"".join(chunks) + return self._body + + async def json(self) -> typing.Any: + if not hasattr(self, "_json"): + body = await self.body() + self._json = json.loads(body) + return self._json + + async def form(self) -> FormData: + if not hasattr(self, "_form"): + assert ( + parse_options_header is not None + ), "The `python-multipart` library must be installed to use form parsing." + content_type_header = self.headers.get("Content-Type") + content_type, options = parse_options_header(content_type_header) + if content_type == b"multipart/form-data": + multipart_parser = MultiPartParser(self.headers, self.stream()) + self._form = await multipart_parser.parse() + elif content_type == b"application/x-www-form-urlencoded": + form_parser = FormParser(self.headers, self.stream()) + self._form = await form_parser.parse() + else: + self._form = FormData() + return self._form + + async def close(self) -> None: + if hasattr(self, "_form"): + await self._form.close() + + async def is_disconnected(self) -> bool: + if not self._is_disconnected: + message: Message = {} + + # If message isn't immediately available, move on + with anyio.CancelScope() as cs: + cs.cancel() + message = await self._receive() + + if message.get("type") == "http.disconnect": + self._is_disconnected = True + + return self._is_disconnected + + async def send_push_promise(self, path: str) -> None: + if "http.response.push" in self.scope.get("extensions", {}): + raw_headers = [] + for name in SERVER_PUSH_HEADERS_TO_COPY: + for value in self.headers.getlist(name): + raw_headers.append( + (name.encode("latin-1"), value.encode("latin-1")) + ) + await self._send( + {"type": "http.response.push", "path": path, "headers": raw_headers} + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/responses.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/responses.py new file mode 100644 index 00000000..bc73cb15 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/responses.py @@ -0,0 +1,349 @@ +import http.cookies +import json +import os +import stat +import sys +import typing +from email.utils import formatdate +from functools import partial +from mimetypes import guess_type as mimetypes_guess_type +from urllib.parse import quote + +import anyio + +from starlette._compat import md5_hexdigest +from starlette.background import BackgroundTask +from starlette.concurrency import iterate_in_threadpool +from starlette.datastructures import URL, MutableHeaders +from starlette.types import Receive, Scope, Send + +# Workaround for adding samesite support to pre 3.8 python +http.cookies.Morsel._reserved["samesite"] = "SameSite" # type: ignore + + +# Compatibility wrapper for `mimetypes.guess_type` to support `os.PathLike` on typing.Tuple[typing.Optional[str], typing.Optional[str]]: + if sys.version_info < (3, 8): # pragma: no cover + url = os.fspath(url) + return mimetypes_guess_type(url, strict) + + +class Response: + media_type = None + charset = "utf-8" + + def __init__( + self, + content: typing.Any = None, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + self.status_code = status_code + if media_type is not None: + self.media_type = media_type + self.background = background + self.body = self.render(content) + self.init_headers(headers) + + def render(self, content: typing.Any) -> bytes: + if content is None: + return b"" + if isinstance(content, bytes): + return content + return content.encode(self.charset) + + def init_headers( + self, headers: typing.Optional[typing.Mapping[str, str]] = None + ) -> None: + if headers is None: + raw_headers: typing.List[typing.Tuple[bytes, bytes]] = [] + populate_content_length = True + populate_content_type = True + else: + raw_headers = [ + (k.lower().encode("latin-1"), v.encode("latin-1")) + for k, v in headers.items() + ] + keys = [h[0] for h in raw_headers] + populate_content_length = b"content-length" not in keys + populate_content_type = b"content-type" not in keys + + body = getattr(self, "body", None) + if ( + body is not None + and populate_content_length + and not (self.status_code < 200 or self.status_code in (204, 304)) + ): + content_length = str(len(body)) + raw_headers.append((b"content-length", content_length.encode("latin-1"))) + + content_type = self.media_type + if content_type is not None and populate_content_type: + if content_type.startswith("text/"): + content_type += "; charset=" + self.charset + raw_headers.append((b"content-type", content_type.encode("latin-1"))) + + self.raw_headers = raw_headers + + @property + def headers(self) -> MutableHeaders: + if not hasattr(self, "_headers"): + self._headers = MutableHeaders(raw=self.raw_headers) + return self._headers + + def set_cookie( + self, + key: str, + value: str = "", + max_age: typing.Optional[int] = None, + expires: typing.Optional[int] = None, + path: str = "/", + domain: typing.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: str = "lax", + ) -> None: + cookie: http.cookies.BaseCookie = http.cookies.SimpleCookie() + cookie[key] = value + if max_age is not None: + cookie[key]["max-age"] = max_age + if expires is not None: + cookie[key]["expires"] = expires + if path is not None: + cookie[key]["path"] = path + if domain is not None: + cookie[key]["domain"] = domain + if secure: + cookie[key]["secure"] = True + if httponly: + cookie[key]["httponly"] = True + if samesite is not None: + assert samesite.lower() in [ + "strict", + "lax", + "none", + ], "samesite must be either 'strict', 'lax' or 'none'" + cookie[key]["samesite"] = samesite + cookie_val = cookie.output(header="").strip() + self.raw_headers.append((b"set-cookie", cookie_val.encode("latin-1"))) + + def delete_cookie( + self, + key: str, + path: str = "/", + domain: typing.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: str = "lax", + ) -> None: + self.set_cookie( + key, + max_age=0, + expires=0, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + await send( + { + "type": "http.response.start", + "status": self.status_code, + "headers": self.raw_headers, + } + ) + await send({"type": "http.response.body", "body": self.body}) + + if self.background is not None: + await self.background() + + +class HTMLResponse(Response): + media_type = "text/html" + + +class PlainTextResponse(Response): + media_type = "text/plain" + + +class JSONResponse(Response): + media_type = "application/json" + + def __init__( + self, + content: typing.Any, + status_code: int = 200, + headers: typing.Optional[dict] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + super().__init__(content, status_code, headers, media_type, background) + + def render(self, content: typing.Any) -> bytes: + return json.dumps( + content, + ensure_ascii=False, + allow_nan=False, + indent=None, + separators=(",", ":"), + ).encode("utf-8") + + +class RedirectResponse(Response): + def __init__( + self, + url: typing.Union[str, URL], + status_code: int = 307, + headers: typing.Optional[typing.Mapping[str, str]] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + super().__init__( + content=b"", status_code=status_code, headers=headers, background=background + ) + self.headers["location"] = quote(str(url), safe=":/%#?=@[]!$&'()*+,;") + + +class StreamingResponse(Response): + def __init__( + self, + content: typing.Any, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + if isinstance(content, typing.AsyncIterable): + self.body_iterator = content + else: + self.body_iterator = iterate_in_threadpool(content) + self.status_code = status_code + self.media_type = self.media_type if media_type is None else media_type + self.background = background + self.init_headers(headers) + + async def listen_for_disconnect(self, receive: Receive) -> None: + while True: + message = await receive() + if message["type"] == "http.disconnect": + break + + async def stream_response(self, send: Send) -> None: + await send( + { + "type": "http.response.start", + "status": self.status_code, + "headers": self.raw_headers, + } + ) + async for chunk in self.body_iterator: + if not isinstance(chunk, bytes): + chunk = chunk.encode(self.charset) + await send({"type": "http.response.body", "body": chunk, "more_body": True}) + + await send({"type": "http.response.body", "body": b"", "more_body": False}) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + async with anyio.create_task_group() as task_group: + + async def wrap(func: typing.Callable[[], typing.Coroutine]) -> None: + await func() + task_group.cancel_scope.cancel() + + task_group.start_soon(wrap, partial(self.stream_response, send)) + await wrap(partial(self.listen_for_disconnect, receive)) + + if self.background is not None: + await self.background() + + +class FileResponse(Response): + chunk_size = 64 * 1024 + + def __init__( + self, + path: typing.Union[str, "os.PathLike[str]"], + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + filename: typing.Optional[str] = None, + stat_result: typing.Optional[os.stat_result] = None, + method: typing.Optional[str] = None, + content_disposition_type: str = "attachment", + ) -> None: + self.path = path + self.status_code = status_code + self.filename = filename + self.send_header_only = method is not None and method.upper() == "HEAD" + if media_type is None: + media_type = guess_type(filename or path)[0] or "text/plain" + self.media_type = media_type + self.background = background + self.init_headers(headers) + if self.filename is not None: + content_disposition_filename = quote(self.filename) + if content_disposition_filename != self.filename: + content_disposition = "{}; filename*=utf-8''{}".format( + content_disposition_type, content_disposition_filename + ) + else: + content_disposition = '{}; filename="{}"'.format( + content_disposition_type, self.filename + ) + self.headers.setdefault("content-disposition", content_disposition) + self.stat_result = stat_result + if stat_result is not None: + self.set_stat_headers(stat_result) + + def set_stat_headers(self, stat_result: os.stat_result) -> None: + content_length = str(stat_result.st_size) + last_modified = formatdate(stat_result.st_mtime, usegmt=True) + etag_base = str(stat_result.st_mtime) + "-" + str(stat_result.st_size) + etag = md5_hexdigest(etag_base.encode(), usedforsecurity=False) + + self.headers.setdefault("content-length", content_length) + self.headers.setdefault("last-modified", last_modified) + self.headers.setdefault("etag", etag) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.stat_result is None: + try: + stat_result = await anyio.to_thread.run_sync(os.stat, self.path) + self.set_stat_headers(stat_result) + except FileNotFoundError: + raise RuntimeError(f"File at path {self.path} does not exist.") + else: + mode = stat_result.st_mode + if not stat.S_ISREG(mode): + raise RuntimeError(f"File at path {self.path} is not a file.") + await send( + { + "type": "http.response.start", + "status": self.status_code, + "headers": self.raw_headers, + } + ) + if self.send_header_only: + await send({"type": "http.response.body", "body": b"", "more_body": False}) + else: + async with await anyio.open_file(self.path, mode="rb") as file: + more_body = True + while more_body: + chunk = await file.read(self.chunk_size) + more_body = len(chunk) == self.chunk_size + await send( + { + "type": "http.response.body", + "body": chunk, + "more_body": more_body, + } + ) + if self.background is not None: + await self.background() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/routing.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/routing.py new file mode 100644 index 00000000..7b7dc9b7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/routing.py @@ -0,0 +1,832 @@ +import asyncio +import contextlib +import functools +import inspect +import re +import sys +import traceback +import types +import typing +import warnings +from enum import Enum + +from starlette.concurrency import run_in_threadpool +from starlette.convertors import CONVERTOR_TYPES, Convertor +from starlette.datastructures import URL, Headers, URLPath +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import PlainTextResponse, RedirectResponse +from starlette.types import ASGIApp, Receive, Scope, Send +from starlette.websockets import WebSocket, WebSocketClose + +if sys.version_info >= (3, 7): + from contextlib import asynccontextmanager # pragma: no cover +else: + from contextlib2 import asynccontextmanager # pragma: no cover + + +class NoMatchFound(Exception): + """ + Raised by `.url_for(name, **path_params)` and `.url_path_for(name, **path_params)` + if no matching route exists. + """ + + def __init__(self, name: str, path_params: typing.Dict[str, typing.Any]) -> None: + params = ", ".join(list(path_params.keys())) + super().__init__(f'No route exists for name "{name}" and params "{params}".') + + +class Match(Enum): + NONE = 0 + PARTIAL = 1 + FULL = 2 + + +def iscoroutinefunction_or_partial(obj: typing.Any) -> bool: + """ + Correctly determines if an object is a coroutine function, + including those wrapped in functools.partial objects. + """ + while isinstance(obj, functools.partial): + obj = obj.func + return inspect.iscoroutinefunction(obj) + + +def request_response(func: typing.Callable) -> ASGIApp: + """ + Takes a function or coroutine `func(request) -> response`, + and returns an ASGI application. + """ + is_coroutine = iscoroutinefunction_or_partial(func) + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + request = Request(scope, receive=receive, send=send) + if is_coroutine: + response = await func(request) + else: + response = await run_in_threadpool(func, request) + await response(scope, receive, send) + + return app + + +def websocket_session(func: typing.Callable) -> ASGIApp: + """ + Takes a coroutine `func(session)`, and returns an ASGI application. + """ + # assert asyncio.iscoroutinefunction(func), "WebSocket endpoints must be async" + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + session = WebSocket(scope, receive=receive, send=send) + await func(session) + + return app + + +def get_name(endpoint: typing.Callable) -> str: + if inspect.isroutine(endpoint) or inspect.isclass(endpoint): + return endpoint.__name__ + return endpoint.__class__.__name__ + + +def replace_params( + path: str, + param_convertors: typing.Dict[str, Convertor], + path_params: typing.Dict[str, str], +) -> typing.Tuple[str, dict]: + for key, value in list(path_params.items()): + if "{" + key + "}" in path: + convertor = param_convertors[key] + value = convertor.to_string(value) + path = path.replace("{" + key + "}", value) + path_params.pop(key) + return path, path_params + + +# Match parameters in URL paths, eg. '{param}', and '{param:int}' +PARAM_REGEX = re.compile("{([a-zA-Z_][a-zA-Z0-9_]*)(:[a-zA-Z_][a-zA-Z0-9_]*)?}") + + +def compile_path( + path: str, +) -> typing.Tuple[typing.Pattern, str, typing.Dict[str, Convertor]]: + """ + Given a path string, like: "/{username:str}", return a three-tuple + of (regex, format, {param_name:convertor}). + + regex: "/(?P[^/]+)" + format: "/{username}" + convertors: {"username": StringConvertor()} + """ + path_regex = "^" + path_format = "" + duplicated_params = set() + + idx = 0 + param_convertors = {} + for match in PARAM_REGEX.finditer(path): + param_name, convertor_type = match.groups("str") + convertor_type = convertor_type.lstrip(":") + assert ( + convertor_type in CONVERTOR_TYPES + ), f"Unknown path convertor '{convertor_type}'" + convertor = CONVERTOR_TYPES[convertor_type] + + path_regex += re.escape(path[idx : match.start()]) + path_regex += f"(?P<{param_name}>{convertor.regex})" + + path_format += path[idx : match.start()] + path_format += "{%s}" % param_name + + if param_name in param_convertors: + duplicated_params.add(param_name) + + param_convertors[param_name] = convertor + + idx = match.end() + + if duplicated_params: + names = ", ".join(sorted(duplicated_params)) + ending = "s" if len(duplicated_params) > 1 else "" + raise ValueError(f"Duplicated param name{ending} {names} at path {path}") + + path_regex += re.escape(path[idx:].split(":")[0]) + "$" + path_format += path[idx:] + + return re.compile(path_regex), path_format, param_convertors + + +class BaseRoute: + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + raise NotImplementedError() # pragma: no cover + + def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: + raise NotImplementedError() # pragma: no cover + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + raise NotImplementedError() # pragma: no cover + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + A route may be used in isolation as a stand-alone ASGI app. + This is a somewhat contrived case, as they'll almost always be used + within a Router, but could be useful for some tooling and minimal apps. + """ + match, child_scope = self.matches(scope) + if match == Match.NONE: + if scope["type"] == "http": + response = PlainTextResponse("Not Found", status_code=404) + await response(scope, receive, send) + elif scope["type"] == "websocket": + websocket_close = WebSocketClose() + await websocket_close(scope, receive, send) + return + + scope.update(child_scope) + await self.handle(scope, receive, send) + + +class Route(BaseRoute): + def __init__( + self, + path: str, + endpoint: typing.Callable, + *, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> None: + assert path.startswith("/"), "Routed paths must start with '/'" + self.path = path + self.endpoint = endpoint + self.name = get_name(endpoint) if name is None else name + self.include_in_schema = include_in_schema + + endpoint_handler = endpoint + while isinstance(endpoint_handler, functools.partial): + endpoint_handler = endpoint_handler.func + if inspect.isfunction(endpoint_handler) or inspect.ismethod(endpoint_handler): + # Endpoint is function or method. Treat it as `func(request) -> response`. + self.app = request_response(endpoint) + if methods is None: + methods = ["GET"] + else: + # Endpoint is a class. Treat it as ASGI. + self.app = endpoint + + if methods is None: + self.methods = None + else: + self.methods = {method.upper() for method in methods} + if "GET" in self.methods: + self.methods.add("HEAD") + + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] == "http": + match = self.path_regex.match(scope["path"]) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + child_scope = {"endpoint": self.endpoint, "path_params": path_params} + if self.methods and scope["method"] not in self.methods: + return Match.PARTIAL, child_scope + else: + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: + seen_params = set(path_params.keys()) + expected_params = set(self.param_convertors.keys()) + + if name != self.name or seen_params != expected_params: + raise NoMatchFound(name, path_params) + + path, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + assert not remaining_params + return URLPath(path=path, protocol="http") + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.methods and scope["method"] not in self.methods: + headers = {"Allow": ", ".join(self.methods)} + if "app" in scope: + raise HTTPException(status_code=405, headers=headers) + else: + response = PlainTextResponse( + "Method Not Allowed", status_code=405, headers=headers + ) + await response(scope, receive, send) + else: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, Route) + and self.path == other.path + and self.endpoint == other.endpoint + and self.methods == other.methods + ) + + +class WebSocketRoute(BaseRoute): + def __init__( + self, path: str, endpoint: typing.Callable, *, name: typing.Optional[str] = None + ) -> None: + assert path.startswith("/"), "Routed paths must start with '/'" + self.path = path + self.endpoint = endpoint + self.name = get_name(endpoint) if name is None else name + + endpoint_handler = endpoint + while isinstance(endpoint_handler, functools.partial): + endpoint_handler = endpoint_handler.func + if inspect.isfunction(endpoint_handler) or inspect.ismethod(endpoint_handler): + # Endpoint is function or method. Treat it as `func(websocket)`. + self.app = websocket_session(endpoint) + else: + # Endpoint is a class. Treat it as ASGI. + self.app = endpoint + + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] == "websocket": + match = self.path_regex.match(scope["path"]) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + child_scope = {"endpoint": self.endpoint, "path_params": path_params} + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: + seen_params = set(path_params.keys()) + expected_params = set(self.param_convertors.keys()) + + if name != self.name or seen_params != expected_params: + raise NoMatchFound(name, path_params) + + path, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + assert not remaining_params + return URLPath(path=path, protocol="websocket") + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, WebSocketRoute) + and self.path == other.path + and self.endpoint == other.endpoint + ) + + +class Mount(BaseRoute): + def __init__( + self, + path: str, + app: typing.Optional[ASGIApp] = None, + routes: typing.Optional[typing.Sequence[BaseRoute]] = None, + name: typing.Optional[str] = None, + ) -> None: + assert path == "" or path.startswith("/"), "Routed paths must start with '/'" + assert ( + app is not None or routes is not None + ), "Either 'app=...', or 'routes=' must be specified" + self.path = path.rstrip("/") + if app is not None: + self.app: ASGIApp = app + else: + self.app = Router(routes=routes) + self.name = name + self.path_regex, self.path_format, self.param_convertors = compile_path( + self.path + "/{path:path}" + ) + + @property + def routes(self) -> typing.List[BaseRoute]: + return getattr(self.app, "routes", []) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] in ("http", "websocket"): + path = scope["path"] + match = self.path_regex.match(path) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + remaining_path = "/" + matched_params.pop("path") + matched_path = path[: -len(remaining_path)] + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + root_path = scope.get("root_path", "") + child_scope = { + "path_params": path_params, + "app_root_path": scope.get("app_root_path", root_path), + "root_path": root_path + matched_path, + "path": remaining_path, + "endpoint": self.app, + } + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: + if self.name is not None and name == self.name and "path" in path_params: + # 'name' matches "". + path_params["path"] = path_params["path"].lstrip("/") + path, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + if not remaining_params: + return URLPath(path=path) + elif self.name is None or name.startswith(self.name + ":"): + if self.name is None: + # No mount name. + remaining_name = name + else: + # 'name' matches ":". + remaining_name = name[len(self.name) + 1 :] + path_kwarg = path_params.get("path") + path_params["path"] = "" + path_prefix, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + if path_kwarg is not None: + remaining_params["path"] = path_kwarg + for route in self.routes or []: + try: + url = route.url_path_for(remaining_name, **remaining_params) + return URLPath( + path=path_prefix.rstrip("/") + str(url), protocol=url.protocol + ) + except NoMatchFound: + pass + raise NoMatchFound(name, path_params) + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, Mount) + and self.path == other.path + and self.app == other.app + ) + + +class Host(BaseRoute): + def __init__( + self, host: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: + self.host = host + self.app = app + self.name = name + self.host_regex, self.host_format, self.param_convertors = compile_path(host) + + @property + def routes(self) -> typing.List[BaseRoute]: + return getattr(self.app, "routes", []) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] in ("http", "websocket"): + headers = Headers(scope=scope) + host = headers.get("host", "").split(":")[0] + match = self.host_regex.match(host) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + child_scope = {"path_params": path_params, "endpoint": self.app} + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: + if self.name is not None and name == self.name and "path" in path_params: + # 'name' matches "". + path = path_params.pop("path") + host, remaining_params = replace_params( + self.host_format, self.param_convertors, path_params + ) + if not remaining_params: + return URLPath(path=path, host=host) + elif self.name is None or name.startswith(self.name + ":"): + if self.name is None: + # No mount name. + remaining_name = name + else: + # 'name' matches ":". + remaining_name = name[len(self.name) + 1 :] + host, remaining_params = replace_params( + self.host_format, self.param_convertors, path_params + ) + for route in self.routes or []: + try: + url = route.url_path_for(remaining_name, **remaining_params) + return URLPath(path=str(url), protocol=url.protocol, host=host) + except NoMatchFound: + pass + raise NoMatchFound(name, path_params) + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, Host) + and self.host == other.host + and self.app == other.app + ) + + +_T = typing.TypeVar("_T") + + +class _AsyncLiftContextManager(typing.AsyncContextManager[_T]): + def __init__(self, cm: typing.ContextManager[_T]): + self._cm = cm + + async def __aenter__(self) -> _T: + return self._cm.__enter__() + + async def __aexit__( + self, + exc_type: typing.Optional[typing.Type[BaseException]], + exc_value: typing.Optional[BaseException], + traceback: typing.Optional[types.TracebackType], + ) -> typing.Optional[bool]: + return self._cm.__exit__(exc_type, exc_value, traceback) + + +def _wrap_gen_lifespan_context( + lifespan_context: typing.Callable[[typing.Any], typing.Generator] +) -> typing.Callable[[typing.Any], typing.AsyncContextManager]: + cmgr = contextlib.contextmanager(lifespan_context) + + @functools.wraps(cmgr) + def wrapper(app: typing.Any) -> _AsyncLiftContextManager: + return _AsyncLiftContextManager(cmgr(app)) + + return wrapper + + +class _DefaultLifespan: + def __init__(self, router: "Router"): + self._router = router + + async def __aenter__(self) -> None: + await self._router.startup() + + async def __aexit__(self, *exc_info: object) -> None: + await self._router.shutdown() + + def __call__(self: _T, app: object) -> _T: + return self + + +class Router: + def __init__( + self, + routes: typing.Optional[typing.Sequence[BaseRoute]] = None, + redirect_slashes: bool = True, + default: typing.Optional[ASGIApp] = None, + on_startup: typing.Optional[typing.Sequence[typing.Callable]] = None, + on_shutdown: typing.Optional[typing.Sequence[typing.Callable]] = None, + lifespan: typing.Optional[ + typing.Callable[[typing.Any], typing.AsyncContextManager] + ] = None, + ) -> None: + self.routes = [] if routes is None else list(routes) + self.redirect_slashes = redirect_slashes + self.default = self.not_found if default is None else default + self.on_startup = [] if on_startup is None else list(on_startup) + self.on_shutdown = [] if on_shutdown is None else list(on_shutdown) + + if lifespan is None: + self.lifespan_context: typing.Callable[ + [typing.Any], typing.AsyncContextManager + ] = _DefaultLifespan(self) + + elif inspect.isasyncgenfunction(lifespan): + warnings.warn( + "async generator function lifespans are deprecated, " + "use an @contextlib.asynccontextmanager function instead", + DeprecationWarning, + ) + self.lifespan_context = asynccontextmanager( + lifespan, # type: ignore[arg-type] + ) + elif inspect.isgeneratorfunction(lifespan): + warnings.warn( + "generator function lifespans are deprecated, " + "use an @contextlib.asynccontextmanager function instead", + DeprecationWarning, + ) + self.lifespan_context = _wrap_gen_lifespan_context( + lifespan, # type: ignore[arg-type] + ) + else: + self.lifespan_context = lifespan + + async def not_found(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] == "websocket": + websocket_close = WebSocketClose() + await websocket_close(scope, receive, send) + return + + # If we're running inside a starlette application then raise an + # exception, so that the configurable exception handler can deal with + # returning the response. For plain ASGI apps, just return the response. + if "app" in scope: + raise HTTPException(status_code=404) + else: + response = PlainTextResponse("Not Found", status_code=404) + await response(scope, receive, send) + + def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: + for route in self.routes: + try: + return route.url_path_for(name, **path_params) + except NoMatchFound: + pass + raise NoMatchFound(name, path_params) + + async def startup(self) -> None: + """ + Run any `.on_startup` event handlers. + """ + for handler in self.on_startup: + if asyncio.iscoroutinefunction(handler): + await handler() + else: + handler() + + async def shutdown(self) -> None: + """ + Run any `.on_shutdown` event handlers. + """ + for handler in self.on_shutdown: + if asyncio.iscoroutinefunction(handler): + await handler() + else: + handler() + + async def lifespan(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + Handle ASGI lifespan messages, which allows us to manage application + startup and shutdown events. + """ + started = False + app = scope.get("app") + await receive() + try: + async with self.lifespan_context(app): + await send({"type": "lifespan.startup.complete"}) + started = True + await receive() + except BaseException: + exc_text = traceback.format_exc() + if started: + await send({"type": "lifespan.shutdown.failed", "message": exc_text}) + else: + await send({"type": "lifespan.startup.failed", "message": exc_text}) + raise + else: + await send({"type": "lifespan.shutdown.complete"}) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + The main entry point to the Router class. + """ + assert scope["type"] in ("http", "websocket", "lifespan") + + if "router" not in scope: + scope["router"] = self + + if scope["type"] == "lifespan": + await self.lifespan(scope, receive, send) + return + + partial = None + + for route in self.routes: + # Determine if any route matches the incoming scope, + # and hand over to the matching route if found. + match, child_scope = route.matches(scope) + if match == Match.FULL: + scope.update(child_scope) + await route.handle(scope, receive, send) + return + elif match == Match.PARTIAL and partial is None: + partial = route + partial_scope = child_scope + + if partial is not None: + #  Handle partial matches. These are cases where an endpoint is + # able to handle the request, but is not a preferred option. + # We use this in particular to deal with "405 Method Not Allowed". + scope.update(partial_scope) + await partial.handle(scope, receive, send) + return + + if scope["type"] == "http" and self.redirect_slashes and scope["path"] != "/": + redirect_scope = dict(scope) + if scope["path"].endswith("/"): + redirect_scope["path"] = redirect_scope["path"].rstrip("/") + else: + redirect_scope["path"] = redirect_scope["path"] + "/" + + for route in self.routes: + match, child_scope = route.matches(redirect_scope) + if match != Match.NONE: + redirect_url = URL(scope=redirect_scope) + response = RedirectResponse(url=str(redirect_url)) + await response(scope, receive, send) + return + + await self.default(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return isinstance(other, Router) and self.routes == other.routes + + # The following usages are now discouraged in favour of configuration + #  during Router.__init__(...) + def mount( + self, path: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: nocover + """ + We no longer document this API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + Mount(path, ...), + ... + ] + + app = Starlette(routes=routes) + """ + + route = Mount(path, app=app, name=name) + self.routes.append(route) + + def host( + self, host: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + """ + We no longer document this API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + Host(path, ...), + ... + ] + + app = Starlette(routes=routes) + """ + + route = Host(host, app=app, name=name) + self.routes.append(route) + + def add_route( + self, + path: str, + endpoint: typing.Callable, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> None: # pragma: nocover + route = Route( + path, + endpoint=endpoint, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + self.routes.append(route) + + def add_websocket_route( + self, path: str, endpoint: typing.Callable, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + route = WebSocketRoute(path, endpoint=endpoint, name=name) + self.routes.append(route) + + def route( + self, + path: str, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> typing.Callable: # pragma: nocover + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + Route(path, endpoint=..., ...), + ... + ] + + app = Starlette(routes=routes) + """ + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_route( + path, + func, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + return func + + return decorator + + def websocket_route( + self, path: str, name: typing.Optional[str] = None + ) -> typing.Callable: # pragma: nocover + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + routes = [ + WebSocketRoute(path, endpoint=..., ...), + ... + ] + + app = Starlette(routes=routes) + """ + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_websocket_route(path, func, name=name) + return func + + return decorator + + def add_event_handler( + self, event_type: str, func: typing.Callable + ) -> None: # pragma: no cover + assert event_type in ("startup", "shutdown") + + if event_type == "startup": + self.on_startup.append(func) + else: + self.on_shutdown.append(func) + + def on_event(self, event_type: str) -> typing.Callable: # pragma: nocover + def decorator(func: typing.Callable) -> typing.Callable: + self.add_event_handler(event_type, func) + return func + + return decorator diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/schemas.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/schemas.py new file mode 100644 index 00000000..6ca764fd --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/schemas.py @@ -0,0 +1,135 @@ +import inspect +import typing + +from starlette.requests import Request +from starlette.responses import Response +from starlette.routing import BaseRoute, Mount, Route + +try: + import yaml +except ImportError: # pragma: nocover + yaml = None # type: ignore + + +class OpenAPIResponse(Response): + media_type = "application/vnd.oai.openapi" + + def render(self, content: typing.Any) -> bytes: + assert yaml is not None, "`pyyaml` must be installed to use OpenAPIResponse." + assert isinstance( + content, dict + ), "The schema passed to OpenAPIResponse should be a dictionary." + return yaml.dump(content, default_flow_style=False).encode("utf-8") + + +class EndpointInfo(typing.NamedTuple): + path: str + http_method: str + func: typing.Callable + + +class BaseSchemaGenerator: + def get_schema(self, routes: typing.List[BaseRoute]) -> dict: + raise NotImplementedError() # pragma: no cover + + def get_endpoints( + self, routes: typing.List[BaseRoute] + ) -> typing.List[EndpointInfo]: + """ + Given the routes, yields the following information: + + - path + eg: /users/ + - http_method + one of 'get', 'post', 'put', 'patch', 'delete', 'options' + - func + method ready to extract the docstring + """ + endpoints_info: list = [] + + for route in routes: + if isinstance(route, Mount): + routes = route.routes or [] + sub_endpoints = [ + EndpointInfo( + path="".join((route.path, sub_endpoint.path)), + http_method=sub_endpoint.http_method, + func=sub_endpoint.func, + ) + for sub_endpoint in self.get_endpoints(routes) + ] + endpoints_info.extend(sub_endpoints) + + elif not isinstance(route, Route) or not route.include_in_schema: + continue + + elif inspect.isfunction(route.endpoint) or inspect.ismethod(route.endpoint): + for method in route.methods or ["GET"]: + if method == "HEAD": + continue + endpoints_info.append( + EndpointInfo(route.path, method.lower(), route.endpoint) + ) + else: + for method in ["get", "post", "put", "patch", "delete", "options"]: + if not hasattr(route.endpoint, method): + continue + func = getattr(route.endpoint, method) + endpoints_info.append( + EndpointInfo(route.path, method.lower(), func) + ) + + return endpoints_info + + def parse_docstring(self, func_or_method: typing.Callable) -> dict: + """ + Given a function, parse the docstring as YAML and return a dictionary of info. + """ + docstring = func_or_method.__doc__ + if not docstring: + return {} + + assert yaml is not None, "`pyyaml` must be installed to use parse_docstring." + + # We support having regular docstrings before the schema + # definition. Here we return just the schema part from + # the docstring. + docstring = docstring.split("---")[-1] + + parsed = yaml.safe_load(docstring) + + if not isinstance(parsed, dict): + # A regular docstring (not yaml formatted) can return + # a simple string here, which wouldn't follow the schema. + return {} + + return parsed + + def OpenAPIResponse(self, request: Request) -> Response: + routes = request.app.routes + schema = self.get_schema(routes=routes) + return OpenAPIResponse(schema) + + +class SchemaGenerator(BaseSchemaGenerator): + def __init__(self, base_schema: dict) -> None: + self.base_schema = base_schema + + def get_schema(self, routes: typing.List[BaseRoute]) -> dict: + schema = dict(self.base_schema) + schema.setdefault("paths", {}) + endpoints_info = self.get_endpoints(routes) + + for endpoint in endpoints_info: + + parsed = self.parse_docstring(endpoint.func) + + if not parsed: + continue + + if endpoint.path not in schema["paths"]: + schema["paths"][endpoint.path] = {} + + schema["paths"][endpoint.path][endpoint.http_method] = parsed + + return schema diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/staticfiles.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/staticfiles.py new file mode 100644 index 00000000..d09630f3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/staticfiles.py @@ -0,0 +1,240 @@ +import importlib.util +import os +import stat +import typing +from email.utils import parsedate + +import anyio + +from starlette.datastructures import URL, Headers +from starlette.exceptions import HTTPException +from starlette.responses import FileResponse, RedirectResponse, Response +from starlette.types import Receive, Scope, Send + +PathLike = typing.Union[str, "os.PathLike[str]"] + + +class NotModifiedResponse(Response): + NOT_MODIFIED_HEADERS = ( + "cache-control", + "content-location", + "date", + "etag", + "expires", + "vary", + ) + + def __init__(self, headers: Headers): + super().__init__( + status_code=304, + headers={ + name: value + for name, value in headers.items() + if name in self.NOT_MODIFIED_HEADERS + }, + ) + + +class StaticFiles: + def __init__( + self, + *, + directory: typing.Optional[PathLike] = None, + packages: typing.Optional[ + typing.List[typing.Union[str, typing.Tuple[str, str]]] + ] = None, + html: bool = False, + check_dir: bool = True, + ) -> None: + self.directory = directory + self.packages = packages + self.all_directories = self.get_directories(directory, packages) + self.html = html + self.config_checked = False + if check_dir and directory is not None and not os.path.isdir(directory): + raise RuntimeError(f"Directory '{directory}' does not exist") + + def get_directories( + self, + directory: typing.Optional[PathLike] = None, + packages: typing.Optional[ + typing.List[typing.Union[str, typing.Tuple[str, str]]] + ] = None, + ) -> typing.List[PathLike]: + """ + Given `directory` and `packages` arguments, return a list of all the + directories that should be used for serving static files from. + """ + directories = [] + if directory is not None: + directories.append(directory) + + for package in packages or []: + if isinstance(package, tuple): + package, statics_dir = package + else: + statics_dir = "statics" + spec = importlib.util.find_spec(package) + assert spec is not None, f"Package {package!r} could not be found." + assert spec.origin is not None, f"Package {package!r} could not be found." + package_directory = os.path.normpath( + os.path.join(spec.origin, "..", statics_dir) + ) + assert os.path.isdir( + package_directory + ), f"Directory '{statics_dir!r}' in package {package!r} could not be found." + directories.append(package_directory) + + return directories + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + The ASGI entry point. + """ + assert scope["type"] == "http" + + if not self.config_checked: + await self.check_config() + self.config_checked = True + + path = self.get_path(scope) + response = await self.get_response(path, scope) + await response(scope, receive, send) + + def get_path(self, scope: Scope) -> str: + """ + Given the ASGI scope, return the `path` string to serve up, + with OS specific path separators, and any '..', '.' components removed. + """ + return os.path.normpath(os.path.join(*scope["path"].split("/"))) + + async def get_response(self, path: str, scope: Scope) -> Response: + """ + Returns an HTTP response, given the incoming path, method and request headers. + """ + if scope["method"] not in ("GET", "HEAD"): + raise HTTPException(status_code=405) + + try: + full_path, stat_result = await anyio.to_thread.run_sync( + self.lookup_path, path + ) + except PermissionError: + raise HTTPException(status_code=401) + except OSError: + raise + + if stat_result and stat.S_ISREG(stat_result.st_mode): + # We have a static file to serve. + return self.file_response(full_path, stat_result, scope) + + elif stat_result and stat.S_ISDIR(stat_result.st_mode) and self.html: + # We're in HTML mode, and have got a directory URL. + # Check if we have 'index.html' file to serve. + index_path = os.path.join(path, "index.html") + full_path, stat_result = await anyio.to_thread.run_sync( + self.lookup_path, index_path + ) + if stat_result is not None and stat.S_ISREG(stat_result.st_mode): + if not scope["path"].endswith("/"): + # Directory URLs should redirect to always end in "/". + url = URL(scope=scope) + url = url.replace(path=url.path + "/") + return RedirectResponse(url=url) + return self.file_response(full_path, stat_result, scope) + + if self.html: + # Check for '404.html' if we're in HTML mode. + full_path, stat_result = await anyio.to_thread.run_sync( + self.lookup_path, "404.html" + ) + if stat_result and stat.S_ISREG(stat_result.st_mode): + return FileResponse( + full_path, + stat_result=stat_result, + method=scope["method"], + status_code=404, + ) + raise HTTPException(status_code=404) + + def lookup_path( + self, path: str + ) -> typing.Tuple[str, typing.Optional[os.stat_result]]: + for directory in self.all_directories: + full_path = os.path.realpath(os.path.join(directory, path)) + directory = os.path.realpath(directory) + if os.path.commonprefix([full_path, directory]) != directory: + # Don't allow misbehaving clients to break out of the static files + # directory. + continue + try: + return full_path, os.stat(full_path) + except (FileNotFoundError, NotADirectoryError): + continue + return "", None + + def file_response( + self, + full_path: PathLike, + stat_result: os.stat_result, + scope: Scope, + status_code: int = 200, + ) -> Response: + method = scope["method"] + request_headers = Headers(scope=scope) + + response = FileResponse( + full_path, status_code=status_code, stat_result=stat_result, method=method + ) + if self.is_not_modified(response.headers, request_headers): + return NotModifiedResponse(response.headers) + return response + + async def check_config(self) -> None: + """ + Perform a one-off configuration check that StaticFiles is actually + pointed at a directory, so that we can raise loud errors rather than + just returning 404 responses. + """ + if self.directory is None: + return + + try: + stat_result = await anyio.to_thread.run_sync(os.stat, self.directory) + except FileNotFoundError: + raise RuntimeError( + f"StaticFiles directory '{self.directory}' does not exist." + ) + if not (stat.S_ISDIR(stat_result.st_mode) or stat.S_ISLNK(stat_result.st_mode)): + raise RuntimeError( + f"StaticFiles path '{self.directory}' is not a directory." + ) + + def is_not_modified( + self, response_headers: Headers, request_headers: Headers + ) -> bool: + """ + Given the request and response headers, return `True` if an HTTP + "Not Modified" response could be returned instead. + """ + try: + if_none_match = request_headers["if-none-match"] + etag = response_headers["etag"] + if if_none_match == etag: + return True + except KeyError: + pass + + try: + if_modified_since = parsedate(request_headers["if-modified-since"]) + last_modified = parsedate(response_headers["last-modified"]) + if ( + if_modified_since is not None + and last_modified is not None + and if_modified_since >= last_modified + ): + return True + except KeyError: + pass + + return False diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/status.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/status.py new file mode 100644 index 00000000..cc52d896 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/status.py @@ -0,0 +1,206 @@ +""" +HTTP codes +See HTTP Status Code Registry: +https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + +And RFC 2324 - https://tools.ietf.org/html/rfc2324 +""" +import sys +import warnings +from typing import List + +from starlette._pep562 import pep562 + +__all__ = ( + "HTTP_100_CONTINUE", + "HTTP_101_SWITCHING_PROTOCOLS", + "HTTP_102_PROCESSING", + "HTTP_103_EARLY_HINTS", + "HTTP_200_OK", + "HTTP_201_CREATED", + "HTTP_202_ACCEPTED", + "HTTP_203_NON_AUTHORITATIVE_INFORMATION", + "HTTP_204_NO_CONTENT", + "HTTP_205_RESET_CONTENT", + "HTTP_206_PARTIAL_CONTENT", + "HTTP_207_MULTI_STATUS", + "HTTP_208_ALREADY_REPORTED", + "HTTP_226_IM_USED", + "HTTP_300_MULTIPLE_CHOICES", + "HTTP_301_MOVED_PERMANENTLY", + "HTTP_302_FOUND", + "HTTP_303_SEE_OTHER", + "HTTP_304_NOT_MODIFIED", + "HTTP_305_USE_PROXY", + "HTTP_306_RESERVED", + "HTTP_307_TEMPORARY_REDIRECT", + "HTTP_308_PERMANENT_REDIRECT", + "HTTP_400_BAD_REQUEST", + "HTTP_401_UNAUTHORIZED", + "HTTP_402_PAYMENT_REQUIRED", + "HTTP_403_FORBIDDEN", + "HTTP_404_NOT_FOUND", + "HTTP_405_METHOD_NOT_ALLOWED", + "HTTP_406_NOT_ACCEPTABLE", + "HTTP_407_PROXY_AUTHENTICATION_REQUIRED", + "HTTP_408_REQUEST_TIMEOUT", + "HTTP_409_CONFLICT", + "HTTP_410_GONE", + "HTTP_411_LENGTH_REQUIRED", + "HTTP_412_PRECONDITION_FAILED", + "HTTP_413_REQUEST_ENTITY_TOO_LARGE", + "HTTP_414_REQUEST_URI_TOO_LONG", + "HTTP_415_UNSUPPORTED_MEDIA_TYPE", + "HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE", + "HTTP_417_EXPECTATION_FAILED", + "HTTP_418_IM_A_TEAPOT", + "HTTP_421_MISDIRECTED_REQUEST", + "HTTP_422_UNPROCESSABLE_ENTITY", + "HTTP_423_LOCKED", + "HTTP_424_FAILED_DEPENDENCY", + "HTTP_425_TOO_EARLY", + "HTTP_426_UPGRADE_REQUIRED", + "HTTP_428_PRECONDITION_REQUIRED", + "HTTP_429_TOO_MANY_REQUESTS", + "HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE", + "HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS", + "HTTP_500_INTERNAL_SERVER_ERROR", + "HTTP_501_NOT_IMPLEMENTED", + "HTTP_502_BAD_GATEWAY", + "HTTP_503_SERVICE_UNAVAILABLE", + "HTTP_504_GATEWAY_TIMEOUT", + "HTTP_505_HTTP_VERSION_NOT_SUPPORTED", + "HTTP_506_VARIANT_ALSO_NEGOTIATES", + "HTTP_507_INSUFFICIENT_STORAGE", + "HTTP_508_LOOP_DETECTED", + "HTTP_510_NOT_EXTENDED", + "HTTP_511_NETWORK_AUTHENTICATION_REQUIRED", + "WS_1000_NORMAL_CLOSURE", + "WS_1001_GOING_AWAY", + "WS_1002_PROTOCOL_ERROR", + "WS_1003_UNSUPPORTED_DATA", + "WS_1005_NO_STATUS_RCVD", + "WS_1006_ABNORMAL_CLOSURE", + "WS_1007_INVALID_FRAME_PAYLOAD_DATA", + "WS_1008_POLICY_VIOLATION", + "WS_1009_MESSAGE_TOO_BIG", + "WS_1010_MANDATORY_EXT", + "WS_1011_INTERNAL_ERROR", + "WS_1012_SERVICE_RESTART", + "WS_1013_TRY_AGAIN_LATER", + "WS_1014_BAD_GATEWAY", + "WS_1015_TLS_HANDSHAKE", +) + +HTTP_100_CONTINUE = 100 +HTTP_101_SWITCHING_PROTOCOLS = 101 +HTTP_102_PROCESSING = 102 +HTTP_103_EARLY_HINTS = 103 +HTTP_200_OK = 200 +HTTP_201_CREATED = 201 +HTTP_202_ACCEPTED = 202 +HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203 +HTTP_204_NO_CONTENT = 204 +HTTP_205_RESET_CONTENT = 205 +HTTP_206_PARTIAL_CONTENT = 206 +HTTP_207_MULTI_STATUS = 207 +HTTP_208_ALREADY_REPORTED = 208 +HTTP_226_IM_USED = 226 +HTTP_300_MULTIPLE_CHOICES = 300 +HTTP_301_MOVED_PERMANENTLY = 301 +HTTP_302_FOUND = 302 +HTTP_303_SEE_OTHER = 303 +HTTP_304_NOT_MODIFIED = 304 +HTTP_305_USE_PROXY = 305 +HTTP_306_RESERVED = 306 +HTTP_307_TEMPORARY_REDIRECT = 307 +HTTP_308_PERMANENT_REDIRECT = 308 +HTTP_400_BAD_REQUEST = 400 +HTTP_401_UNAUTHORIZED = 401 +HTTP_402_PAYMENT_REQUIRED = 402 +HTTP_403_FORBIDDEN = 403 +HTTP_404_NOT_FOUND = 404 +HTTP_405_METHOD_NOT_ALLOWED = 405 +HTTP_406_NOT_ACCEPTABLE = 406 +HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407 +HTTP_408_REQUEST_TIMEOUT = 408 +HTTP_409_CONFLICT = 409 +HTTP_410_GONE = 410 +HTTP_411_LENGTH_REQUIRED = 411 +HTTP_412_PRECONDITION_FAILED = 412 +HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413 +HTTP_414_REQUEST_URI_TOO_LONG = 414 +HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415 +HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416 +HTTP_417_EXPECTATION_FAILED = 417 +HTTP_418_IM_A_TEAPOT = 418 +HTTP_421_MISDIRECTED_REQUEST = 421 +HTTP_422_UNPROCESSABLE_ENTITY = 422 +HTTP_423_LOCKED = 423 +HTTP_424_FAILED_DEPENDENCY = 424 +HTTP_425_TOO_EARLY = 425 +HTTP_426_UPGRADE_REQUIRED = 426 +HTTP_428_PRECONDITION_REQUIRED = 428 +HTTP_429_TOO_MANY_REQUESTS = 429 +HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431 +HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451 +HTTP_500_INTERNAL_SERVER_ERROR = 500 +HTTP_501_NOT_IMPLEMENTED = 501 +HTTP_502_BAD_GATEWAY = 502 +HTTP_503_SERVICE_UNAVAILABLE = 503 +HTTP_504_GATEWAY_TIMEOUT = 504 +HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505 +HTTP_506_VARIANT_ALSO_NEGOTIATES = 506 +HTTP_507_INSUFFICIENT_STORAGE = 507 +HTTP_508_LOOP_DETECTED = 508 +HTTP_510_NOT_EXTENDED = 510 +HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511 + + +""" +WebSocket codes +https://www.iana.org/assignments/websocket/websocket.xml#close-code-number +https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent +""" +WS_1000_NORMAL_CLOSURE = 1000 +WS_1001_GOING_AWAY = 1001 +WS_1002_PROTOCOL_ERROR = 1002 +WS_1003_UNSUPPORTED_DATA = 1003 +WS_1005_NO_STATUS_RCVD = 1005 +WS_1006_ABNORMAL_CLOSURE = 1006 +WS_1007_INVALID_FRAME_PAYLOAD_DATA = 1007 +WS_1008_POLICY_VIOLATION = 1008 +WS_1009_MESSAGE_TOO_BIG = 1009 +WS_1010_MANDATORY_EXT = 1010 +WS_1011_INTERNAL_ERROR = 1011 +WS_1012_SERVICE_RESTART = 1012 +WS_1013_TRY_AGAIN_LATER = 1013 +WS_1014_BAD_GATEWAY = 1014 +WS_1015_TLS_HANDSHAKE = 1015 + + +__deprecated__ = {"WS_1004_NO_STATUS_RCVD": 1004, "WS_1005_ABNORMAL_CLOSURE": 1005} + + +def __getattr__(name: str) -> int: + deprecation_changes = { + "WS_1004_NO_STATUS_RCVD": "WS_1005_NO_STATUS_RCVD", + "WS_1005_ABNORMAL_CLOSURE": "WS_1006_ABNORMAL_CLOSURE", + } + deprecated = __deprecated__.get(name) + if deprecated: + stacklevel = 3 if sys.version_info >= (3, 7) else 4 + warnings.warn( + f"'{name}' is deprecated. Use '{deprecation_changes[name]}' instead.", + category=DeprecationWarning, + stacklevel=stacklevel, + ) + return deprecated + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") + + +def __dir__() -> List[str]: + return sorted(list(__all__) + list(__deprecated__.keys())) # pragma: no cover + + +pep562(__name__) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/templating.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/templating.py new file mode 100644 index 00000000..99035837 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/templating.py @@ -0,0 +1,105 @@ +import typing +from os import PathLike + +from starlette.background import BackgroundTask +from starlette.responses import Response +from starlette.types import Receive, Scope, Send + +try: + import jinja2 + + # @contextfunction was renamed to @pass_context in Jinja 3.0, and was removed in 3.1 + # hence we try to get pass_context (most installs will be >=3.1) + # and fall back to contextfunction, + # adding a type ignore for mypy to let us access an attribute that may not exist + if hasattr(jinja2, "pass_context"): + pass_context = jinja2.pass_context + else: # pragma: nocover + pass_context = jinja2.contextfunction # type: ignore[attr-defined] +except ImportError: # pragma: nocover + jinja2 = None # type: ignore + + +class _TemplateResponse(Response): + media_type = "text/html" + + def __init__( + self, + template: typing.Any, + context: dict, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ): + self.template = template + self.context = context + content = template.render(context) + super().__init__(content, status_code, headers, media_type, background) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + request = self.context.get("request", {}) + extensions = request.get("extensions", {}) + if "http.response.template" in extensions: + await send( + { + "type": "http.response.template", + "template": self.template, + "context": self.context, + } + ) + await super().__call__(scope, receive, send) + + +class Jinja2Templates: + """ + templates = Jinja2Templates("templates") + + return templates.TemplateResponse("index.html", {"request": request}) + """ + + def __init__( + self, directory: typing.Union[str, PathLike], **env_options: typing.Any + ) -> None: + assert jinja2 is not None, "jinja2 must be installed to use Jinja2Templates" + self.env = self._create_env(directory, **env_options) + + def _create_env( + self, directory: typing.Union[str, PathLike], **env_options: typing.Any + ) -> "jinja2.Environment": + @pass_context + def url_for(context: dict, name: str, **path_params: typing.Any) -> str: + request = context["request"] + return request.url_for(name, **path_params) + + loader = jinja2.FileSystemLoader(directory) + env_options.setdefault("loader", loader) + env_options.setdefault("autoescape", True) + + env = jinja2.Environment(**env_options) + env.globals["url_for"] = url_for + return env + + def get_template(self, name: str) -> "jinja2.Template": + return self.env.get_template(name) + + def TemplateResponse( + self, + name: str, + context: dict, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> _TemplateResponse: + if "request" not in context: + raise ValueError('context must include a "request" key') + template = self.get_template(name) + return _TemplateResponse( + template, + context, + status_code=status_code, + headers=headers, + media_type=media_type, + background=background, + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/testclient.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/testclient.py new file mode 100644 index 00000000..7567d18f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/testclient.py @@ -0,0 +1,584 @@ +import asyncio +import contextlib +import http +import inspect +import io +import json +import math +import queue +import sys +import types +import typing +from concurrent.futures import Future +from urllib.parse import unquote, urljoin, urlsplit + +import anyio.abc +import requests +from anyio.streams.stapled import StapledObjectStream + +from starlette.types import Message, Receive, Scope, Send +from starlette.websockets import WebSocketDisconnect + +if sys.version_info >= (3, 8): # pragma: no cover + from typing import TypedDict +else: # pragma: no cover + from typing_extensions import TypedDict + + +_PortalFactoryType = typing.Callable[ + [], typing.ContextManager[anyio.abc.BlockingPortal] +] + + +# Annotations for `Session.request()` +Cookies = typing.Union[ + typing.MutableMapping[str, str], requests.cookies.RequestsCookieJar +] +Params = typing.Union[bytes, typing.MutableMapping[str, str]] +DataType = typing.Union[bytes, typing.MutableMapping[str, str], typing.IO] +TimeOut = typing.Union[float, typing.Tuple[float, float]] +FileType = typing.MutableMapping[str, typing.IO] +AuthType = typing.Union[ + typing.Tuple[str, str], + requests.auth.AuthBase, + typing.Callable[[requests.PreparedRequest], requests.PreparedRequest], +] + + +ASGIInstance = typing.Callable[[Receive, Send], typing.Awaitable[None]] +ASGI2App = typing.Callable[[Scope], ASGIInstance] +ASGI3App = typing.Callable[[Scope, Receive, Send], typing.Awaitable[None]] + + +class _HeaderDict(requests.packages.urllib3._collections.HTTPHeaderDict): + def get_all(self, key: str, default: str) -> str: + return self.getheaders(key) + + +class _MockOriginalResponse: + """ + We have to jump through some hoops to present the response as if + it was made using urllib3. + """ + + def __init__(self, headers: typing.List[typing.Tuple[bytes, bytes]]) -> None: + self.msg = _HeaderDict(headers) + self.closed = False + + def isclosed(self) -> bool: + return self.closed + + +class _Upgrade(Exception): + def __init__(self, session: "WebSocketTestSession") -> None: + self.session = session + + +def _get_reason_phrase(status_code: int) -> str: + try: + return http.HTTPStatus(status_code).phrase + except ValueError: + return "" + + +def _is_asgi3(app: typing.Union[ASGI2App, ASGI3App]) -> bool: + if inspect.isclass(app): + return hasattr(app, "__await__") + elif inspect.isfunction(app): + return asyncio.iscoroutinefunction(app) + call = getattr(app, "__call__", None) + return asyncio.iscoroutinefunction(call) + + +class _WrapASGI2: + """ + Provide an ASGI3 interface onto an ASGI2 app. + """ + + def __init__(self, app: ASGI2App) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + instance = self.app(scope) + await instance(receive, send) + + +class _AsyncBackend(TypedDict): + backend: str + backend_options: typing.Dict[str, typing.Any] + + +class _ASGIAdapter(requests.adapters.HTTPAdapter): + def __init__( + self, + app: ASGI3App, + portal_factory: _PortalFactoryType, + raise_server_exceptions: bool = True, + root_path: str = "", + ) -> None: + self.app = app + self.raise_server_exceptions = raise_server_exceptions + self.root_path = root_path + self.portal_factory = portal_factory + + def send( + self, request: requests.PreparedRequest, *args: typing.Any, **kwargs: typing.Any + ) -> requests.Response: + scheme, netloc, path, query, fragment = ( + str(item) for item in urlsplit(request.url) + ) + + default_port = {"http": 80, "ws": 80, "https": 443, "wss": 443}[scheme] + + if ":" in netloc: + host, port_string = netloc.split(":", 1) + port = int(port_string) + else: + host = netloc + port = default_port + + # Include the 'host' header. + if "host" in request.headers: + headers: typing.List[typing.Tuple[bytes, bytes]] = [] + elif port == default_port: + headers = [(b"host", host.encode())] + else: + headers = [(b"host", (f"{host}:{port}").encode())] + + # Include other request headers. + headers += [ + (key.lower().encode(), value.encode()) + for key, value in request.headers.items() + ] + + scope: typing.Dict[str, typing.Any] + + if scheme in {"ws", "wss"}: + subprotocol = request.headers.get("sec-websocket-protocol", None) + if subprotocol is None: + subprotocols: typing.Sequence[str] = [] + else: + subprotocols = [value.strip() for value in subprotocol.split(",")] + scope = { + "type": "websocket", + "path": unquote(path), + "raw_path": path.encode(), + "root_path": self.root_path, + "scheme": scheme, + "query_string": query.encode(), + "headers": headers, + "client": ["testclient", 50000], + "server": [host, port], + "subprotocols": subprotocols, + } + session = WebSocketTestSession(self.app, scope, self.portal_factory) + raise _Upgrade(session) + + scope = { + "type": "http", + "http_version": "1.1", + "method": request.method, + "path": unquote(path), + "raw_path": path.encode(), + "root_path": self.root_path, + "scheme": scheme, + "query_string": query.encode(), + "headers": headers, + "client": ["testclient", 50000], + "server": [host, port], + "extensions": {"http.response.template": {}}, + } + + request_complete = False + response_started = False + response_complete: anyio.Event + raw_kwargs: typing.Dict[str, typing.Any] = {"body": io.BytesIO()} + template = None + context = None + + async def receive() -> Message: + nonlocal request_complete + + if request_complete: + if not response_complete.is_set(): + await response_complete.wait() + return {"type": "http.disconnect"} + + body = request.body + if isinstance(body, str): + body_bytes: bytes = body.encode("utf-8") + elif body is None: + body_bytes = b"" + elif isinstance(body, types.GeneratorType): + try: + chunk = body.send(None) + if isinstance(chunk, str): + chunk = chunk.encode("utf-8") + return {"type": "http.request", "body": chunk, "more_body": True} + except StopIteration: + request_complete = True + return {"type": "http.request", "body": b""} + else: + body_bytes = body + + request_complete = True + return {"type": "http.request", "body": body_bytes} + + async def send(message: Message) -> None: + nonlocal raw_kwargs, response_started, template, context + + if message["type"] == "http.response.start": + assert ( + not response_started + ), 'Received multiple "http.response.start" messages.' + raw_kwargs["version"] = 11 + raw_kwargs["status"] = message["status"] + raw_kwargs["reason"] = _get_reason_phrase(message["status"]) + raw_kwargs["headers"] = [ + (key.decode(), value.decode()) + for key, value in message.get("headers", []) + ] + raw_kwargs["preload_content"] = False + raw_kwargs["original_response"] = _MockOriginalResponse( + raw_kwargs["headers"] + ) + response_started = True + elif message["type"] == "http.response.body": + assert ( + response_started + ), 'Received "http.response.body" without "http.response.start".' + assert ( + not response_complete.is_set() + ), 'Received "http.response.body" after response completed.' + body = message.get("body", b"") + more_body = message.get("more_body", False) + if request.method != "HEAD": + raw_kwargs["body"].write(body) + if not more_body: + raw_kwargs["body"].seek(0) + response_complete.set() + elif message["type"] == "http.response.template": + template = message["template"] + context = message["context"] + + try: + with self.portal_factory() as portal: + response_complete = portal.call(anyio.Event) + portal.call(self.app, scope, receive, send) + except BaseException as exc: + if self.raise_server_exceptions: + raise exc + + if self.raise_server_exceptions: + assert response_started, "TestClient did not receive any response." + elif not response_started: + raw_kwargs = { + "version": 11, + "status": 500, + "reason": "Internal Server Error", + "headers": [], + "preload_content": False, + "original_response": _MockOriginalResponse([]), + "body": io.BytesIO(), + } + + raw = requests.packages.urllib3.HTTPResponse(**raw_kwargs) + response = self.build_response(request, raw) + if template is not None: + response.template = template + response.context = context + return response + + +class WebSocketTestSession: + def __init__( + self, + app: ASGI3App, + scope: Scope, + portal_factory: _PortalFactoryType, + ) -> None: + self.app = app + self.scope = scope + self.accepted_subprotocol = None + self.extra_headers = None + self.portal_factory = portal_factory + self._receive_queue: "queue.Queue[typing.Any]" = queue.Queue() + self._send_queue: "queue.Queue[typing.Any]" = queue.Queue() + + def __enter__(self) -> "WebSocketTestSession": + self.exit_stack = contextlib.ExitStack() + self.portal = self.exit_stack.enter_context(self.portal_factory()) + + try: + _: "Future[None]" = self.portal.start_task_soon(self._run) + self.send({"type": "websocket.connect"}) + message = self.receive() + self._raise_on_close(message) + except Exception: + self.exit_stack.close() + raise + self.accepted_subprotocol = message.get("subprotocol", None) + self.extra_headers = message.get("headers", None) + return self + + def __exit__(self, *args: typing.Any) -> None: + try: + self.close(1000) + finally: + self.exit_stack.close() + while not self._send_queue.empty(): + message = self._send_queue.get() + if isinstance(message, BaseException): + raise message + + async def _run(self) -> None: + """ + The sub-thread in which the websocket session runs. + """ + scope = self.scope + receive = self._asgi_receive + send = self._asgi_send + try: + await self.app(scope, receive, send) + except BaseException as exc: + self._send_queue.put(exc) + raise + + async def _asgi_receive(self) -> Message: + while self._receive_queue.empty(): + await anyio.sleep(0) + return self._receive_queue.get() + + async def _asgi_send(self, message: Message) -> None: + self._send_queue.put(message) + + def _raise_on_close(self, message: Message) -> None: + if message["type"] == "websocket.close": + raise WebSocketDisconnect( + message.get("code", 1000), message.get("reason", "") + ) + + def send(self, message: Message) -> None: + self._receive_queue.put(message) + + def send_text(self, data: str) -> None: + self.send({"type": "websocket.receive", "text": data}) + + def send_bytes(self, data: bytes) -> None: + self.send({"type": "websocket.receive", "bytes": data}) + + def send_json(self, data: typing.Any, mode: str = "text") -> None: + assert mode in ["text", "binary"] + text = json.dumps(data) + if mode == "text": + self.send({"type": "websocket.receive", "text": text}) + else: + self.send({"type": "websocket.receive", "bytes": text.encode("utf-8")}) + + def close(self, code: int = 1000) -> None: + self.send({"type": "websocket.disconnect", "code": code}) + + def receive(self) -> Message: + message = self._send_queue.get() + if isinstance(message, BaseException): + raise message + return message + + def receive_text(self) -> str: + message = self.receive() + self._raise_on_close(message) + return message["text"] + + def receive_bytes(self) -> bytes: + message = self.receive() + self._raise_on_close(message) + return message["bytes"] + + def receive_json(self, mode: str = "text") -> typing.Any: + assert mode in ["text", "binary"] + message = self.receive() + self._raise_on_close(message) + if mode == "text": + text = message["text"] + else: + text = message["bytes"].decode("utf-8") + return json.loads(text) + + +class TestClient(requests.Session): + __test__ = False # For pytest to not discover this up. + task: "Future[None]" + portal: typing.Optional[anyio.abc.BlockingPortal] = None + + def __init__( + self, + app: typing.Union[ASGI2App, ASGI3App], + base_url: str = "http://testserver", + raise_server_exceptions: bool = True, + root_path: str = "", + backend: str = "asyncio", + backend_options: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> None: + super().__init__() + self.async_backend = _AsyncBackend( + backend=backend, backend_options=backend_options or {} + ) + if _is_asgi3(app): + app = typing.cast(ASGI3App, app) + asgi_app = app + else: + app = typing.cast(ASGI2App, app) + asgi_app = _WrapASGI2(app) #  type: ignore + adapter = _ASGIAdapter( + asgi_app, + portal_factory=self._portal_factory, + raise_server_exceptions=raise_server_exceptions, + root_path=root_path, + ) + self.mount("http://", adapter) + self.mount("https://", adapter) + self.mount("ws://", adapter) + self.mount("wss://", adapter) + self.headers.update({"user-agent": "testclient"}) + self.app = asgi_app + self.base_url = base_url + + @contextlib.contextmanager + def _portal_factory( + self, + ) -> typing.Generator[anyio.abc.BlockingPortal, None, None]: + if self.portal is not None: + yield self.portal + else: + with anyio.start_blocking_portal(**self.async_backend) as portal: + yield portal + + def request( # type: ignore + self, + method: str, + url: str, + params: Params = None, + data: DataType = None, + headers: typing.MutableMapping[str, str] = None, + cookies: Cookies = None, + files: FileType = None, + auth: AuthType = None, + timeout: TimeOut = None, + allow_redirects: bool = None, + proxies: typing.MutableMapping[str, str] = None, + hooks: typing.Any = None, + stream: bool = None, + verify: typing.Union[bool, str] = None, + cert: typing.Union[str, typing.Tuple[str, str]] = None, + json: typing.Any = None, + ) -> requests.Response: + url = urljoin(self.base_url, url) + return super().request( + method, + url, + params=params, + data=data, + headers=headers, + cookies=cookies, + files=files, + auth=auth, + timeout=timeout, + allow_redirects=allow_redirects, + proxies=proxies, + hooks=hooks, + stream=stream, + verify=verify, + cert=cert, + json=json, + ) + + def websocket_connect( + self, url: str, subprotocols: typing.Sequence[str] = None, **kwargs: typing.Any + ) -> typing.Any: + url = urljoin("ws://testserver", url) + headers = kwargs.get("headers", {}) + headers.setdefault("connection", "upgrade") + headers.setdefault("sec-websocket-key", "testserver==") + headers.setdefault("sec-websocket-version", "13") + if subprotocols is not None: + headers.setdefault("sec-websocket-protocol", ", ".join(subprotocols)) + kwargs["headers"] = headers + try: + super().request("GET", url, **kwargs) + except _Upgrade as exc: + session = exc.session + else: + raise RuntimeError("Expected WebSocket upgrade") # pragma: no cover + + return session + + def __enter__(self) -> "TestClient": + with contextlib.ExitStack() as stack: + self.portal = portal = stack.enter_context( + anyio.start_blocking_portal(**self.async_backend) + ) + + @stack.callback + def reset_portal() -> None: + self.portal = None + + self.stream_send = StapledObjectStream( + *anyio.create_memory_object_stream(math.inf) + ) + self.stream_receive = StapledObjectStream( + *anyio.create_memory_object_stream(math.inf) + ) + self.task = portal.start_task_soon(self.lifespan) + portal.call(self.wait_startup) + + @stack.callback + def wait_shutdown() -> None: + portal.call(self.wait_shutdown) + + self.exit_stack = stack.pop_all() + + return self + + def __exit__(self, *args: typing.Any) -> None: + self.exit_stack.close() + + async def lifespan(self) -> None: + scope = {"type": "lifespan"} + try: + await self.app(scope, self.stream_receive.receive, self.stream_send.send) + finally: + await self.stream_send.send(None) + + async def wait_startup(self) -> None: + await self.stream_receive.send({"type": "lifespan.startup"}) + + async def receive() -> typing.Any: + message = await self.stream_send.receive() + if message is None: + self.task.result() + return message + + message = await receive() + assert message["type"] in ( + "lifespan.startup.complete", + "lifespan.startup.failed", + ) + if message["type"] == "lifespan.startup.failed": + await receive() + + async def wait_shutdown(self) -> None: + async def receive() -> typing.Any: + message = await self.stream_send.receive() + if message is None: + self.task.result() + return message + + async with self.stream_send: + await self.stream_receive.send({"type": "lifespan.shutdown"}) + message = await receive() + assert message["type"] in ( + "lifespan.shutdown.complete", + "lifespan.shutdown.failed", + ) + if message["type"] == "lifespan.shutdown.failed": + await receive() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/types.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/types.py new file mode 100644 index 00000000..888645ca --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/types.py @@ -0,0 +1,9 @@ +import typing + +Scope = typing.MutableMapping[str, typing.Any] +Message = typing.MutableMapping[str, typing.Any] + +Receive = typing.Callable[[], typing.Awaitable[Message]] +Send = typing.Callable[[Message], typing.Awaitable[None]] + +ASGIApp = typing.Callable[[Scope, Receive, Send], typing.Awaitable[None]] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/websockets.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/websockets.py new file mode 100644 index 00000000..afcbde7f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/starlette/websockets.py @@ -0,0 +1,193 @@ +import enum +import json +import typing + +from starlette.requests import HTTPConnection +from starlette.types import Message, Receive, Scope, Send + + +class WebSocketState(enum.Enum): + CONNECTING = 0 + CONNECTED = 1 + DISCONNECTED = 2 + + +class WebSocketDisconnect(Exception): + def __init__(self, code: int = 1000, reason: typing.Optional[str] = None) -> None: + self.code = code + self.reason = reason or "" + + +class WebSocket(HTTPConnection): + def __init__(self, scope: Scope, receive: Receive, send: Send) -> None: + super().__init__(scope) + assert scope["type"] == "websocket" + self._receive = receive + self._send = send + self.client_state = WebSocketState.CONNECTING + self.application_state = WebSocketState.CONNECTING + + async def receive(self) -> Message: + """ + Receive ASGI websocket messages, ensuring valid state transitions. + """ + if self.client_state == WebSocketState.CONNECTING: + message = await self._receive() + message_type = message["type"] + if message_type != "websocket.connect": + raise RuntimeError( + 'Expected ASGI message "websocket.connect", ' + f"but got {message_type!r}" + ) + self.client_state = WebSocketState.CONNECTED + return message + elif self.client_state == WebSocketState.CONNECTED: + message = await self._receive() + message_type = message["type"] + if message_type not in {"websocket.receive", "websocket.disconnect"}: + raise RuntimeError( + 'Expected ASGI message "websocket.receive" or ' + f'"websocket.disconnect", but got {message_type!r}' + ) + if message_type == "websocket.disconnect": + self.client_state = WebSocketState.DISCONNECTED + return message + else: + raise RuntimeError( + 'Cannot call "receive" once a disconnect message has been received.' + ) + + async def send(self, message: Message) -> None: + """ + Send ASGI websocket messages, ensuring valid state transitions. + """ + if self.application_state == WebSocketState.CONNECTING: + message_type = message["type"] + if message_type not in {"websocket.accept", "websocket.close"}: + raise RuntimeError( + 'Expected ASGI message "websocket.connect", ' + f"but got {message_type!r}" + ) + if message_type == "websocket.close": + self.application_state = WebSocketState.DISCONNECTED + else: + self.application_state = WebSocketState.CONNECTED + await self._send(message) + elif self.application_state == WebSocketState.CONNECTED: + message_type = message["type"] + if message_type not in {"websocket.send", "websocket.close"}: + raise RuntimeError( + 'Expected ASGI message "websocket.send" or "websocket.close", ' + f"but got {message_type!r}" + ) + if message_type == "websocket.close": + self.application_state = WebSocketState.DISCONNECTED + await self._send(message) + else: + raise RuntimeError('Cannot call "send" once a close message has been sent.') + + async def accept( + self, + subprotocol: typing.Optional[str] = None, + headers: typing.Optional[typing.Iterable[typing.Tuple[bytes, bytes]]] = None, + ) -> None: + headers = headers or [] + + if self.client_state == WebSocketState.CONNECTING: + # If we haven't yet seen the 'connect' message, then wait for it first. + await self.receive() + await self.send( + {"type": "websocket.accept", "subprotocol": subprotocol, "headers": headers} + ) + + def _raise_on_disconnect(self, message: Message) -> None: + if message["type"] == "websocket.disconnect": + raise WebSocketDisconnect(message["code"]) + + async def receive_text(self) -> str: + if self.application_state != WebSocketState.CONNECTED: + raise RuntimeError( + 'WebSocket is not connected. Need to call "accept" first.' + ) + message = await self.receive() + self._raise_on_disconnect(message) + return message["text"] + + async def receive_bytes(self) -> bytes: + if self.application_state != WebSocketState.CONNECTED: + raise RuntimeError( + 'WebSocket is not connected. Need to call "accept" first.' + ) + message = await self.receive() + self._raise_on_disconnect(message) + return message["bytes"] + + async def receive_json(self, mode: str = "text") -> typing.Any: + if mode not in {"text", "binary"}: + raise RuntimeError('The "mode" argument should be "text" or "binary".') + if self.application_state != WebSocketState.CONNECTED: + raise RuntimeError( + 'WebSocket is not connected. Need to call "accept" first.' + ) + message = await self.receive() + self._raise_on_disconnect(message) + + if mode == "text": + text = message["text"] + else: + text = message["bytes"].decode("utf-8") + return json.loads(text) + + async def iter_text(self) -> typing.AsyncIterator[str]: + try: + while True: + yield await self.receive_text() + except WebSocketDisconnect: + pass + + async def iter_bytes(self) -> typing.AsyncIterator[bytes]: + try: + while True: + yield await self.receive_bytes() + except WebSocketDisconnect: + pass + + async def iter_json(self) -> typing.AsyncIterator[typing.Any]: + try: + while True: + yield await self.receive_json() + except WebSocketDisconnect: + pass + + async def send_text(self, data: str) -> None: + await self.send({"type": "websocket.send", "text": data}) + + async def send_bytes(self, data: bytes) -> None: + await self.send({"type": "websocket.send", "bytes": data}) + + async def send_json(self, data: typing.Any, mode: str = "text") -> None: + if mode not in {"text", "binary"}: + raise RuntimeError('The "mode" argument should be "text" or "binary".') + text = json.dumps(data) + if mode == "text": + await self.send({"type": "websocket.send", "text": text}) + else: + await self.send({"type": "websocket.send", "bytes": text.encode("utf-8")}) + + async def close( + self, code: int = 1000, reason: typing.Optional[str] = None + ) -> None: + await self.send( + {"type": "websocket.close", "code": code, "reason": reason or ""} + ) + + +class WebSocketClose: + def __init__(self, code: int = 1000, reason: typing.Optional[str] = None) -> None: + self.code = code + self.reason = reason or "" + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + await send( + {"type": "websocket.close", "code": self.code, "reason": self.reason} + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/LICENSE new file mode 100644 index 00000000..583f9f6e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/LICENSE @@ -0,0 +1,254 @@ +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations (now Zope +Corporation, see http://www.zope.com). In 2001, the Python Software +Foundation (PSF, see http://www.python.org/psf/) was formed, a +non-profit organization created specifically to own Python-related +Intellectual Property. Zope Corporation is a sponsoring member of +the PSF. + +All Python releases are Open Source (see http://www.opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014 Python Software Foundation; All Rights Reserved" are +retained in Python alone or in any derivative version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the Internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the Internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/METADATA new file mode 100644 index 00000000..30236884 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/METADATA @@ -0,0 +1,176 @@ +Metadata-Version: 2.1 +Name: typing_extensions +Version: 4.3.0 +Summary: Backported and Experimental Type Hints for Python 3.7+ +Keywords: annotations,backport,checker,checking,function,hinting,hints,type,typechecking,typehinting,typehints,typing +Author-email: "Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee" +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Python Software Foundation License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Topic :: Software Development +Project-URL: Bug Tracker, https://github.com/python/typing_extensions/issues +Project-URL: Changes, https://github.com/python/typing_extensions/blob/main/CHANGELOG.md +Project-URL: Documentation, https://typing.readthedocs.io/ +Project-URL: Home, https://github.com/python/typing_extensions +Project-URL: Q & A, https://github.com/python/typing/discussions +Project-URL: Repository, https://github.com/python/typing_extensions + +# Typing Extensions + +[![Chat at https://gitter.im/python/typing](https://badges.gitter.im/python/typing.svg)](https://gitter.im/python/typing) + +## Overview + +The `typing_extensions` module serves two related purposes: + +- Enable use of new type system features on older Python versions. For example, + `typing.TypeGuard` is new in Python 3.10, but `typing_extensions` allows + users on Python 3.6 through 3.9 to use it too. +- Enable experimentation with new type system PEPs before they are accepted and + added to the `typing` module. + +New features may be added to `typing_extensions` as soon as they are specified +in a PEP that has been added to the [python/peps](https://github.com/python/peps) +repository. If the PEP is accepted, the feature will then be added to `typing` +for the next CPython release. No typing PEP has been rejected so far, so we +haven't yet figured out how to deal with that possibility. + +Starting with version 4.0.0, `typing_extensions` uses +[Semantic Versioning](https://semver.org/). The +major version is incremented for all backwards-incompatible changes. +Therefore, it's safe to depend +on `typing_extensions` like this: `typing_extensions >=x.y, <(x+1)`, +where `x.y` is the first version that includes all features you need. + +`typing_extensions` supports Python versions 3.7 and higher. In the future, +support for older Python versions will be dropped some time after that version +reaches end of life. + +## Included items + +This module currently contains the following: + +- Experimental features + + - (Currently none) + +- In `typing` since Python 3.11 + + - `assert_never` + - `assert_type` + - `clear_overloads` + - `@dataclass_transform()` (see PEP 681) + - `get_overloads` + - `LiteralString` (see PEP 675) + - `Never` + - `NotRequired` (see PEP 655) + - `reveal_type` + - `Required` (see PEP 655) + - `Self` (see PEP 673) + - `TypeVarTuple` (see PEP 646) + - `Unpack` (see PEP 646) + +- In `typing` since Python 3.10 + + - `Concatenate` (see PEP 612) + - `ParamSpec` (see PEP 612) + - `ParamSpecArgs` (see PEP 612) + - `ParamSpecKwargs` (see PEP 612) + - `TypeAlias` (see PEP 613) + - `TypeGuard` (see PEP 647) + - `is_typeddict` + +- In `typing` since Python 3.9 + + - `Annotated` (see PEP 593) + +- In `typing` since Python 3.8 + + - `final` (see PEP 591) + - `Final` (see PEP 591) + - `Literal` (see PEP 586) + - `Protocol` (see PEP 544) + - `runtime_checkable` (see PEP 544) + - `TypedDict` (see PEP 589) + - `get_origin` (`typing_extensions` provides this function only in Python 3.7+) + - `get_args` (`typing_extensions` provides this function only in Python 3.7+) + +- In `typing` since Python 3.7 + + - `OrderedDict` + +- In `typing` since Python 3.5 or 3.6 (see [the typing documentation](https://docs.python.org/3.10/library/typing.html) for details) + + - `AsyncContextManager` + - `AsyncGenerator` + - `AsyncIterable` + - `AsyncIterator` + - `Awaitable` + - `ChainMap` + - `ClassVar` (see PEP 526) + - `ContextManager` + - `Coroutine` + - `Counter` + - `DefaultDict` + - `Deque` + - `NamedTuple` + - `NewType` + - `NoReturn` + - `overload` + - `Text` + - `Type` + - `TYPE_CHECKING` + - `get_type_hints` + +# Other Notes and Limitations + +Certain objects were changed after they were added to `typing`, and +`typing_extensions` provides a backport even on newer Python versions: + +- `TypedDict` does not store runtime information + about which (if any) keys are non-required in Python 3.8, and does not + honor the `total` keyword with old-style `TypedDict()` in Python + 3.9.0 and 3.9.1. `TypedDict` also does not support multiple inheritance + with `typing.Generic` on Python <3.11. +- `get_origin` and `get_args` lack support for `Annotated` in + Python 3.8 and lack support for `ParamSpecArgs` and `ParamSpecKwargs` + in 3.9. +- `@final` was changed in Python 3.11 to set the `.__final__` attribute. +- `@overload` was changed in Python 3.11 to make function overloads + introspectable at runtime. In order to access overloads with + `typing_extensions.get_overloads()`, you must use + `@typing_extensions.overload`. +- `NamedTuple` was changed in Python 3.11 to allow for multiple inheritance + with `typing.Generic`. + +There are a few types whose interface was modified between different +versions of typing. For example, `typing.Sequence` was modified to +subclass `typing.Reversible` as of Python 3.5.3. + +These changes are _not_ backported to prevent subtle compatibility +issues when mixing the differing implementations of modified classes. + +Certain types have incorrect runtime behavior due to limitations of older +versions of the typing module: + +- `ParamSpec` and `Concatenate` will not work with `get_args` and + `get_origin`. Certain PEP 612 special cases in user-defined + `Generic`s are also not available. + +These types are only guaranteed to work for static type checking. + +## Running tests + +To run tests, navigate into the appropriate source directory and run +`test_typing_extensions.py`. + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/RECORD new file mode 100644 index 00000000..6e1b4d0c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/RECORD @@ -0,0 +1,7 @@ +__pycache__/typing_extensions.cpython-37.pyc,, +typing_extensions-4.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +typing_extensions-4.3.0.dist-info/LICENSE,sha256=_xfOlOECAk3raHc-scx0ynbaTmWPNzUx8Kwi1oprsa0,12755 +typing_extensions-4.3.0.dist-info/METADATA,sha256=Gc182SCaY3PXonSf1hdCKS9NGE0QLoBnxSS9V9VCOIk,6350 +typing_extensions-4.3.0.dist-info/RECORD,, +typing_extensions-4.3.0.dist-info/WHEEL,sha256=4TfKIB_xu-04bc2iKz6_zFt-gEFEEDU_31HGhqzOCE8,81 +typing_extensions.py,sha256=uZ95U2XP0uVC6SD6OhMsspPxUi7HaLXBIulP58ImWDA,75384 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/WHEEL new file mode 100644 index 00000000..668ba4d0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions-4.3.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.7.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions.py new file mode 100644 index 00000000..31d3564e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/typing_extensions.py @@ -0,0 +1,2069 @@ +import abc +import collections +import collections.abc +import functools +import operator +import sys +import types as _types +import typing + + +# Please keep __all__ alphabetized within each category. +__all__ = [ + # Super-special typing primitives. + 'ClassVar', + 'Concatenate', + 'Final', + 'LiteralString', + 'ParamSpec', + 'ParamSpecArgs', + 'ParamSpecKwargs', + 'Self', + 'Type', + 'TypeVarTuple', + 'Unpack', + + # ABCs (from collections.abc). + 'Awaitable', + 'AsyncIterator', + 'AsyncIterable', + 'Coroutine', + 'AsyncGenerator', + 'AsyncContextManager', + 'ChainMap', + + # Concrete collection types. + 'ContextManager', + 'Counter', + 'Deque', + 'DefaultDict', + 'NamedTuple', + 'OrderedDict', + 'TypedDict', + + # Structural checks, a.k.a. protocols. + 'SupportsIndex', + + # One-off things. + 'Annotated', + 'assert_never', + 'assert_type', + 'clear_overloads', + 'dataclass_transform', + 'get_overloads', + 'final', + 'get_args', + 'get_origin', + 'get_type_hints', + 'IntVar', + 'is_typeddict', + 'Literal', + 'NewType', + 'overload', + 'Protocol', + 'reveal_type', + 'runtime', + 'runtime_checkable', + 'Text', + 'TypeAlias', + 'TypeGuard', + 'TYPE_CHECKING', + 'Never', + 'NoReturn', + 'Required', + 'NotRequired', +] + +# for backward compatibility +PEP_560 = True +GenericMeta = type + +# The functions below are modified copies of typing internal helpers. +# They are needed by _ProtocolMeta and they provide support for PEP 646. + +_marker = object() + + +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: + 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 + raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};" + f" actual {alen}, expected {elen}") + + +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 + + +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 = [] + for t in types: + if ( + isinstance(t, typevar_types) and + t not in tvars and + not _is_unpack(t) + ): + 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) + + +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. + +ClassVar = typing.ClassVar + +# On older versions of typing there is an internal class named "Final". +# 3.8+ +if hasattr(typing, 'Final') and sys.version_info[:2] >= (3, 7): + Final = typing.Final +# 3.7 +else: + class _FinalForm(typing._SpecialForm, _root=True): + + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + Final = _FinalForm('Final', + doc="""A special typing construct to indicate that a name + cannot be re-assigned or overridden in a subclass. + For example: + + MAX_SIZE: Final = 9000 + MAX_SIZE += 1 # Error reported by type checker + + class Connection: + TIMEOUT: Final[int] = 10 + class FastConnector(Connection): + TIMEOUT = 1 # Error reported by type checker + + There is no runtime checking of these properties.""") + +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) + + +# 3.8+: +if hasattr(typing, 'Literal'): + Literal = typing.Literal +# 3.7: +else: + class _LiteralForm(typing._SpecialForm, _root=True): + + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + return typing._GenericAlias(self, parameters) + + Literal = _LiteralForm('Literal', + 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 # noqa + + +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 +ContextManager = typing.ContextManager +AsyncContextManager = typing.AsyncContextManager +DefaultDict = typing.DefaultDict + +# 3.7.2+ +if hasattr(typing, 'OrderedDict'): + OrderedDict = typing.OrderedDict +# 3.7.0-3.7.2 +else: + OrderedDict = typing._alias(collections.OrderedDict, (KT, VT)) + +Counter = typing.Counter +ChainMap = typing.ChainMap +AsyncGenerator = typing.AsyncGenerator +NewType = typing.NewType +Text = typing.Text +TYPE_CHECKING = typing.TYPE_CHECKING + + +_PROTO_WHITELIST = ['Callable', 'Awaitable', + 'Iterable', 'Iterator', 'AsyncIterable', 'AsyncIterator', + 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', + 'ContextManager', 'AsyncContextManager'] + + +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 list(base.__dict__.keys()) + list(annotations.keys()): + if (not attr.startswith('_abc_') and attr not in ( + '__abstractmethods__', '__annotations__', '__weakref__', + '_is_protocol', '_is_runtime_protocol', '__dict__', + '__args__', '__slots__', + '__next_in_mro__', '__parameters__', '__origin__', + '__orig_bases__', '__extra__', '__tree_hash__', + '__doc__', '__subclasshook__', '__init__', '__new__', + '__module__', '_MutableMapping__marker', '_gorg')): + attrs.add(attr) + return attrs + + +def _is_callable_members_only(cls): + return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls)) + + +def _maybe_adjust_parameters(cls): + """Helper function used in Protocol.__init_subclass__ and _TypedDictMeta.__new__. + + The contents of this function are very similar + to logic found in typing.Generic.__init_subclass__ + on the CPython main branch. + """ + tvars = [] + if '__orig_bases__' in cls.__dict__: + tvars = typing._collect_type_vars(cls.__orig_bases__) + # Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn]. + # If found, tvars must be a subset of it. + # If not found, tvars is it. + # Also check for and reject plain Generic, + # and reject multiple Generic[...] and/or Protocol[...]. + gvars = None + for base in cls.__orig_bases__: + if (isinstance(base, typing._GenericAlias) and + base.__origin__ in (typing.Generic, Protocol)): + # for error messages + the_base = base.__origin__.__name__ + if gvars is not None: + raise TypeError( + "Cannot inherit from Generic[...]" + " and/or Protocol[...] multiple types.") + gvars = base.__parameters__ + if gvars is None: + gvars = tvars + else: + tvarset = set(tvars) + gvarset = set(gvars) + if not tvarset <= gvarset: + s_vars = ', '.join(str(t) for t in tvars if t not in gvarset) + s_args = ', '.join(str(g) for g in gvars) + raise TypeError(f"Some type variables ({s_vars}) are" + f" not listed in {the_base}[{s_args}]") + tvars = gvars + cls.__parameters__ = tuple(tvars) + + +# 3.8+ +if hasattr(typing, 'Protocol'): + Protocol = typing.Protocol +# 3.7 +else: + + def _no_init(self, *args, **kwargs): + if type(self)._is_protocol: + raise TypeError('Protocols cannot be instantiated') + + class _ProtocolMeta(abc.ABCMeta): + # This metaclass is a bit unfortunate and exists only because of the lack + # of __instancehook__. + def __instancecheck__(cls, instance): + # We need this method for situations where attributes are + # assigned in __init__. + if ((not getattr(cls, '_is_protocol', False) or + _is_callable_members_only(cls)) and + issubclass(instance.__class__, cls)): + return True + if cls._is_protocol: + if all(hasattr(instance, attr) and + (not callable(getattr(cls, attr, None)) or + getattr(instance, attr) is not None) + for attr in _get_protocol_attrs(cls)): + return True + return super().__instancecheck__(instance) + + class Protocol(metaclass=_ProtocolMeta): + # There is quite a lot of overlapping code with typing.Generic. + # Unfortunately it is hard to avoid this while these live in two different + # modules. The duplicated code will be removed when Protocol is moved to typing. + """Base class for protocol classes. Protocol classes are defined as:: + + class Proto(Protocol): + def meth(self) -> int: + ... + + Such classes are primarily used with static type checkers that recognize + structural subtyping (static duck-typing), for example:: + + class C: + def meth(self) -> int: + return 0 + + def func(x: Proto) -> int: + return x.meth() + + func(C()) # Passes static type check + + See PEP 544 for details. Protocol classes decorated with + @typing_extensions.runtime act as simple-minded runtime protocol that checks + only the presence of given attributes, ignoring their type signatures. + + Protocol classes can be generic, they are defined as:: + + class GenProto(Protocol[T]): + def meth(self) -> T: + ... + """ + __slots__ = () + _is_protocol = True + + def __new__(cls, *args, **kwds): + if cls is Protocol: + raise TypeError("Type Protocol cannot be instantiated; " + "it can only be used as a base class") + return super().__new__(cls) + + @typing._tp_cache + def __class_getitem__(cls, params): + if not isinstance(params, tuple): + params = (params,) + if not params and cls is not typing.Tuple: + raise TypeError( + f"Parameter list to {cls.__qualname__}[...] cannot be empty") + msg = "Parameters to generic types must be types." + params = tuple(typing._type_check(p, msg) for p in params) # noqa + if cls is Protocol: + # Generic can only be subscripted with unique type variables. + if not all(isinstance(p, typing.TypeVar) for p in params): + i = 0 + while isinstance(params[i], typing.TypeVar): + i += 1 + raise TypeError( + "Parameters to Protocol[...] must all be type variables." + f" Parameter {i + 1} is {params[i]}") + if len(set(params)) != len(params): + raise TypeError( + "Parameters to Protocol[...] must all be unique") + else: + # Subscripting a regular Generic subclass. + _check_generic(cls, params, len(cls.__parameters__)) + return typing._GenericAlias(cls, params) + + def __init_subclass__(cls, *args, **kwargs): + if '__orig_bases__' in cls.__dict__: + error = typing.Generic in cls.__orig_bases__ + else: + error = typing.Generic in cls.__bases__ + if error: + raise TypeError("Cannot inherit from plain Generic") + _maybe_adjust_parameters(cls) + + # Determine if this is a protocol or a concrete subclass. + if not cls.__dict__.get('_is_protocol', None): + cls._is_protocol = any(b is Protocol for b in cls.__bases__) + + # Set (or override) the protocol subclass hook. + def _proto_hook(other): + if not cls.__dict__.get('_is_protocol', None): + return NotImplemented + if not getattr(cls, '_is_runtime_protocol', False): + if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']: + return NotImplemented + raise TypeError("Instance and class checks can only be used with" + " @runtime protocols") + if not _is_callable_members_only(cls): + if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']: + return NotImplemented + raise TypeError("Protocols with non-method members" + " don't support issubclass()") + if not isinstance(other, type): + # Same error as for issubclass(1, int) + raise TypeError('issubclass() arg 1 must be a class') + for attr in _get_protocol_attrs(cls): + for base in other.__mro__: + if attr in base.__dict__: + if base.__dict__[attr] is None: + return NotImplemented + break + annotations = getattr(base, '__annotations__', {}) + if (isinstance(annotations, typing.Mapping) and + attr in annotations and + isinstance(other, _ProtocolMeta) and + other._is_protocol): + break + else: + return NotImplemented + return True + if '__subclasshook__' not in cls.__dict__: + cls.__subclasshook__ = _proto_hook + + # We have nothing more to do for non-protocols. + if not cls._is_protocol: + return + + # Check consistency of bases. + for base in cls.__bases__: + if not (base in (object, typing.Generic) or + base.__module__ == 'collections.abc' and + base.__name__ in _PROTO_WHITELIST or + isinstance(base, _ProtocolMeta) and base._is_protocol): + raise TypeError('Protocols can only inherit from other' + f' protocols, got {repr(base)}') + cls.__init__ = _no_init + + +# 3.8+ +if hasattr(typing, 'runtime_checkable'): + runtime_checkable = typing.runtime_checkable +# 3.7 +else: + def runtime_checkable(cls): + """Mark a protocol class as a runtime protocol, so that it + 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 the + one-offs in collections.abc such as Hashable. + """ + if not isinstance(cls, _ProtocolMeta) or not cls._is_protocol: + raise TypeError('@runtime_checkable can be only applied to protocol classes,' + f' got {cls!r}') + cls._is_runtime_protocol = True + return cls + + +# Exists for backwards compatibility. +runtime = runtime_checkable + + +# 3.8+ +if hasattr(typing, 'SupportsIndex'): + SupportsIndex = typing.SupportsIndex +# 3.7 +else: + @runtime_checkable + class SupportsIndex(Protocol): + __slots__ = () + + @abc.abstractmethod + def __index__(self) -> int: + pass + + +if hasattr(typing, "Required"): + # 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. + TypedDict = typing.TypedDict + _TypedDictMeta = typing._TypedDictMeta + is_typeddict = typing.is_typeddict +else: + def _check_fails(cls, other): + try: + if sys._getframe(1).f_globals['__name__'] not in ['abc', + 'functools', + 'typing']: + # Typed dicts are only for static structural subtyping. + raise TypeError('TypedDict does not support instance and class checks') + except (AttributeError, ValueError): + pass + return False + + def _dict_new(*args, **kwargs): + if not args: + raise TypeError('TypedDict.__new__(): not enough arguments') + _, args = args[0], args[1:] # allow the "cls" keyword be passed + return dict(*args, **kwargs) + + _dict_new.__text_signature__ = '($cls, _typename, _fields=None, /, **kwargs)' + + def _typeddict_new(*args, total=True, **kwargs): + if not args: + raise TypeError('TypedDict.__new__(): not enough arguments') + _, args = args[0], args[1:] # allow the "cls" keyword be passed + if args: + typename, args = args[0], args[1:] # allow the "_typename" keyword be passed + elif '_typename' in kwargs: + typename = kwargs.pop('_typename') + import warnings + warnings.warn("Passing '_typename' as keyword argument is deprecated", + DeprecationWarning, stacklevel=2) + else: + raise TypeError("TypedDict.__new__() missing 1 required positional " + "argument: '_typename'") + if args: + try: + fields, = args # allow the "_fields" keyword be passed + except ValueError: + raise TypeError('TypedDict.__new__() takes from 2 to 3 ' + f'positional arguments but {len(args) + 2} ' + 'were given') + elif '_fields' in kwargs and len(kwargs) == 1: + fields = kwargs.pop('_fields') + import warnings + warnings.warn("Passing '_fields' as keyword argument is deprecated", + DeprecationWarning, stacklevel=2) + else: + fields = None + + if fields is None: + fields = kwargs + elif kwargs: + raise TypeError("TypedDict takes either a dict or keyword arguments," + " but not both") + + ns = {'__annotations__': dict(fields)} + try: + # Setting correct module is necessary to make typed dict classes pickleable. + ns['__module__'] = sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + + return _TypedDictMeta(typename, (), ns, total=total) + + _typeddict_new.__text_signature__ = ('($cls, _typename, _fields=None,' + ' /, *, total=True, **kwargs)') + + class _TypedDictMeta(type): + def __init__(cls, name, bases, ns, total=True): + super().__init__(name, bases, ns) + + def __new__(cls, name, bases, ns, total=True): + # Create new typed dict class object. + # This method is called directly when TypedDict is subclassed, + # or via _typeddict_new when TypedDict is instantiated. This way + # TypedDict supports all three syntaxes described in its docstring. + # Subclasses and instances of TypedDict return actual dictionaries + # via _dict_new. + ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new + # Don't insert typing.Generic into __bases__ here, + # or Generic.__init_subclass__ will raise TypeError + # in the super().__new__() call. + # Instead, monkey-patch __bases__ onto the class after it's been created. + tp_dict = super().__new__(cls, name, (dict,), ns) + + if any(issubclass(base, typing.Generic) for base in bases): + tp_dict.__bases__ = (typing.Generic, dict) + _maybe_adjust_parameters(tp_dict) + + annotations = {} + own_annotations = ns.get('__annotations__', {}) + msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" + own_annotations = { + n: typing._type_check(tp, msg) for n, tp in own_annotations.items() + } + required_keys = set() + optional_keys = set() + + for base in bases: + annotations.update(base.__dict__.get('__annotations__', {})) + required_keys.update(base.__dict__.get('__required_keys__', ())) + optional_keys.update(base.__dict__.get('__optional_keys__', ())) + + annotations.update(own_annotations) + for annotation_key, annotation_type in own_annotations.items(): + 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] + annotation_origin = get_origin(annotation_type) + + if annotation_origin is Required: + required_keys.add(annotation_key) + elif annotation_origin is NotRequired: + optional_keys.add(annotation_key) + elif total: + required_keys.add(annotation_key) + else: + optional_keys.add(annotation_key) + + tp_dict.__annotations__ = annotations + tp_dict.__required_keys__ = frozenset(required_keys) + tp_dict.__optional_keys__ = frozenset(optional_keys) + if not hasattr(tp_dict, '__total__'): + tp_dict.__total__ = total + return tp_dict + + __instancecheck__ = __subclasscheck__ = _check_fails + + TypedDict = _TypedDictMeta('TypedDict', (dict,), {}) + TypedDict.__module__ = __name__ + TypedDict.__doc__ = \ + """A simple typed name space. At runtime it is equivalent to a plain dict. + + TypedDict creates a dictionary type that expects all of its + instances to have a certain set of keys, with each key + associated with a value of a consistent type. This expectation + is not checked at runtime but is only enforced by type checkers. + 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 two additional equivalent forms:: + + Point2D = TypedDict('Point2D', x=int, y=int, label=str) + Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) + + The class syntax is only supported in Python 3.6+, while two other + syntax forms work for Python 2.7 and 3.2+ + """ + + 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 + """ + return isinstance(tp, tuple(_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, "Required"): + get_type_hints = typing.get_type_hints +else: + import functools + import types + + # 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): + 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"): + hint = typing.get_type_hints( + obj, globalns=globalns, localns=localns, include_extras=True + ) + else: + 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.7-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.7-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): + class _TypeAliasForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + @_TypeAliasForm + 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.7-3.8 +else: + class _TypeAliasForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + TypeAlias = _TypeAliasForm('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.""") + + +# Python 3.10+ has PEP 612 +if hasattr(typing, 'ParamSpecArgs'): + ParamSpecArgs = typing.ParamSpecArgs + ParamSpecKwargs = typing.ParamSpecKwargs +# 3.7-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__ + +# 3.10+ +if hasattr(typing, 'ParamSpec'): + ParamSpec = typing.ParamSpec +# 3.7-3.9 +else: + + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + class ParamSpec(list): + """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): + super().__init__([self]) + self.__name__ = name + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + if bound: + self.__bound__ = typing._type_check(bound, 'Bound must be a type.') + else: + self.__bound__ = None + + # for pickling: + try: + def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + def_mod = None + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + def __repr__(self): + if 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.7-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.7-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 # noqa +# 3.9 +elif sys.version_info[:2] >= (3, 9): + @_TypeAliasForm + 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.7-8 +else: + class _ConcatenateForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + 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): + class _TypeGuardForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + @_TypeGuardForm + 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.7-3.8 +else: + class _TypeGuardForm(typing._SpecialForm, _root=True): + + def __repr__(self): + return 'typing_extensions.' + self._name + + 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). + """) + + +# 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"): + LiteralString = typing.LiteralString +else: + @_SpecialForm + def LiteralString(self, params): + """Represents an arbitrary literal string. + + Example:: + + from 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"): + 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"): + 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 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'): + Required = typing.Required + NotRequired = typing.NotRequired +elif sys.version_info[:2] >= (3, 9): + class _ExtensionsSpecialForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + @_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: + class _RequiredForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + 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, "Unpack"): # 3.11+ + Unpack = typing.Unpack +elif sys.version_info[:2] >= (3, 9): + class _UnpackSpecialForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + class _UnpackAlias(typing._GenericAlias, _root=True): + __class__ = typing.TypeVar + + @_UnpackSpecialForm + def Unpack(self, parameters): + """A special typing construct to unpack a variadic type. For example: + + Shape = TypeVarTuple('Shape') + Batch = NewType('Batch', int) + + def add_batch_axis( + x: Array[Unpack[Shape]] + ) -> Array[Batch, Unpack[Shape]]: ... + + """ + 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: + class _UnpackAlias(typing._GenericAlias, _root=True): + __class__ = typing.TypeVar + + class _UnpackForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + 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="""A special typing construct to unpack a variadic type. For example: + + Shape = TypeVarTuple('Shape') + Batch = NewType('Batch', int) + + def add_batch_axis( + x: Array[Unpack[Shape]] + ) -> Array[Batch, Unpack[Shape]]: ... + + """) + + def _is_unpack(obj): + return isinstance(obj, _UnpackAlias) + + +if hasattr(typing, "TypeVarTuple"): # 3.11+ + TypeVarTuple = typing.TypeVarTuple +else: + class TypeVarTuple: + """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): + self.__name__ = name + + # for pickling: + try: + def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + def_mod = None + 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"): + reveal_type = typing.reveal_type +else: + 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"): + assert_never = typing.assert_never +else: + 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. + + """ + raise AssertionError("Expected code to be unreachable") + + +if hasattr(typing, 'dataclass_transform'): + dataclass_transform = typing.dataclass_transform +else: + def dataclass_transform( + *, + eq_default: bool = True, + order_default: bool = False, + kw_only_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 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. + - ``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, + "field_specifiers": field_specifiers, + "kwargs": kwargs, + } + return cls_or_fn + return decorator + + +# 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"): + typing._collect_type_vars = _collect_type_vars + typing._check_generic = _check_generic + + +# Backport typing.NamedTuple as it exists in Python 3.11. +# 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. +if sys.version_info >= (3, 11): + NamedTuple = typing.NamedTuple +else: + def _caller(): + try: + return sys._getframe(2).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): # For platforms without _getframe() + return None + + 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) + types = ns.get('__annotations__', {}) + 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: + 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 in ns: + if key in _prohibited_namedtuple_fields: + raise AttributeError("Cannot overwrite NamedTuple attribute " + key) + elif key not in _special_namedtuple_fields and key not in nm_tpl._fields: + setattr(nm_tpl, key, ns[key]) + if typing.Generic in bases: + nm_tpl.__init_subclass__() + return nm_tpl + + def NamedTuple(__typename, __fields=None, **kwargs): + if __fields is None: + __fields = kwargs.items() + elif kwargs: + raise TypeError("Either list of fields or keywords" + " can be provided to NamedTuple, not both") + return _make_nmtuple(__typename, __fields, module=_caller()) + + NamedTuple.__doc__ = typing.NamedTuple.__doc__ + _NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {}) + + # On 3.8+, alter the signature so that it matches typing.NamedTuple. + # The signature of typing.NamedTuple on >=3.8 is invalid syntax in Python 3.7, + # so just leave the signature as it is on 3.7. + if sys.version_info >= (3, 8): + NamedTuple.__text_signature__ = '(typename, fields=None, /, **kwargs)' + + def _namedtuple_mro_entries(bases): + assert NamedTuple in bases + return (_NamedTuple,) + + NamedTuple.__mro_entries__ = _namedtuple_mro_entries diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/METADATA new file mode 100644 index 00000000..e1faca7a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/METADATA @@ -0,0 +1,177 @@ +Metadata-Version: 2.1 +Name: uvicorn +Version: 0.18.3 +Summary: The lightning-fast ASGI server. +Project-URL: Changelog, https://github.com/encode/uvicorn/blob/master/CHANGELOG.md +Project-URL: Funding, https://github.com/sponsors/encode +Project-URL: Homepage, https://www.uvicorn.org/ +Project-URL: Source, https://github.com/encode/uvicorn +Author-email: Tom Christie +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +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 :: Internet :: WWW/HTTP +Requires-Python: >=3.7 +Requires-Dist: click>=7.0 +Requires-Dist: h11>=0.8 +Requires-Dist: typing-extensions; python_version < '3.8' +Provides-Extra: standard +Requires-Dist: colorama>=0.4; sys_platform == 'win32' and extra == 'standard' +Requires-Dist: httptools>=0.4.0; extra == 'standard' +Requires-Dist: python-dotenv>=0.13; extra == 'standard' +Requires-Dist: pyyaml>=5.1; extra == 'standard' +Requires-Dist: uvloop!=0.15.0,!=0.15.1,>=0.14.0; sys_platform != 'win32' and (sys_platform != 'cygwin' and platform_python_implementation != 'PyPy') and extra == 'standard' +Requires-Dist: watchfiles>=0.13; extra == 'standard' +Requires-Dist: websockets>=10.0; extra == 'standard' +Description-Content-Type: text/markdown + +

      + uvicorn +

      + +

      +An ASGI web server, for Python. +

      + +--- + +[![Build Status](https://github.com/encode/uvicorn/workflows/Test%20Suite/badge.svg)](https://github.com/encode/uvicorn/actions) +[![Package version](https://badge.fury.io/py/uvicorn.svg)](https://pypi.python.org/pypi/uvicorn) + +**Documentation**: [https://www.uvicorn.org](https://www.uvicorn.org) + +**Requirements**: Python 3.7+ (For Python 3.6 support, install version 0.16.0.) + +Uvicorn is an ASGI web server implementation for Python. + +Until recently Python has lacked a minimal low-level server/application interface for +async frameworks. The [ASGI specification][asgi] fills this gap, and means we're now able to +start building a common set of tooling usable across all async frameworks. + +Uvicorn supports HTTP/1.1 and WebSockets. + +## Quickstart + +Install using `pip`: + +```shell +$ pip install uvicorn +``` + +This will install uvicorn with minimal (pure Python) dependencies. + +```shell +$ pip install uvicorn[standard] +``` + +This will install uvicorn with "Cython-based" dependencies (where possible) and other "optional extras". + +In this context, "Cython-based" means the following: + +- the event loop `uvloop` will be installed and used if possible. +- the http protocol will be handled by `httptools` if possible. + +Moreover, "optional extras" means that: + +- the websocket protocol will be handled by `websockets` (should you want to use `wsproto` you'd need to install it manually) if possible. +- the `--reload` flag in development mode will use `watchfiles`. +- windows users will have `colorama` installed for the colored logs. +- `python-dotenv` will be installed should you want to use the `--env-file` option. +- `PyYAML` will be installed to allow you to provide a `.yaml` file to `--log-config`, if desired. + +Create an application, in `example.py`: + +```python +async def app(scope, receive, send): + assert scope['type'] == 'http' + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + [b'content-type', b'text/plain'], + ], + }) + await send({ + 'type': 'http.response.body', + 'body': b'Hello, world!', + }) +``` + +Run the server: + +```shell +$ uvicorn example:app +``` + +--- + +## Why ASGI? + +Most well established Python Web frameworks started out as WSGI-based frameworks. + +WSGI applications are a single, synchronous callable that takes a request and returns a response. +This doesn’t allow for long-lived connections, like you get with long-poll HTTP or WebSocket connections, +which WSGI doesn't support well. + +Having an async concurrency model also allows for options such as lightweight background tasks, +and can be less of a limiting factor for endpoints that have long periods being blocked on network +I/O such as dealing with slow HTTP requests. + +--- + +## Alternative ASGI servers + +A strength of the ASGI protocol is that it decouples the server implementation +from the application framework. This allows for an ecosystem of interoperating +webservers and application frameworks. + +### Daphne + +The first ASGI server implementation, originally developed to power Django Channels, is [the Daphne webserver][daphne]. + +It is run widely in production, and supports HTTP/1.1, HTTP/2, and WebSockets. + +Any of the example applications given here can equally well be run using `daphne` instead. + +``` +$ pip install daphne +$ daphne app:App +``` + +### Hypercorn + +[Hypercorn][hypercorn] was initially part of the Quart web framework, before +being separated out into a standalone ASGI server. + +Hypercorn supports HTTP/1.1, HTTP/2, and WebSockets. + +It also supports [the excellent `trio` async framework][trio], as an alternative to `asyncio`. + +``` +$ pip install hypercorn +$ hypercorn app:App +``` + +### Mangum + +[Mangum][mangum] is an adapter for using ASGI applications with AWS Lambda & API Gateway. + +--- + +

      Uvicorn is BSD licensed code.
      Designed & crafted with care.

      — 🦄 —

      + +[asgi]: https://asgi.readthedocs.io/en/latest/ +[daphne]: https://github.com/django/daphne +[hypercorn]: https://gitlab.com/pgjones/hypercorn +[mangum]: https://mangum.io +[trio]: https://trio.readthedocs.io diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/RECORD new file mode 100644 index 00000000..c2fc6772 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/RECORD @@ -0,0 +1,88 @@ +../../Scripts/uvicorn.exe,sha256=E98Re0I2Wk-skGSFXgYT7ZfUw2TaGtBjCN9q2BgsI_k,106373 +uvicorn-0.18.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +uvicorn-0.18.3.dist-info/METADATA,sha256=joHuKDTIFuQ9_WH4jhj-ouJojd0Z6eJeVAQcQhj8YLk,6152 +uvicorn-0.18.3.dist-info/RECORD,, +uvicorn-0.18.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn-0.18.3.dist-info/WHEEL,sha256=3DSmSyYE1SDERO2-rI3qUbMVovBs7--ggc7mubOemsc,86 +uvicorn-0.18.3.dist-info/entry_points.txt,sha256=FW1w-hkc9QgwaGoovMvm0ZY73w_NcycWdGAUfDsNGxw,46 +uvicorn-0.18.3.dist-info/licenses/LICENSE.md,sha256=7-Gs8-YvuZwoiw7HPlp3O3Jo70Mg_nV-qZQhTktjw3E,1526 +uvicorn/__init__.py,sha256=6HPPD-sOC7GB84mf_MAJVb7NjIhvqgpAT0CC2G6BZ8k,147 +uvicorn/__main__.py,sha256=DQizy6nKP0ywhPpnCHgmRDYIMfcqZKVEzNIWQZjqtVQ,62 +uvicorn/__pycache__/__init__.cpython-37.pyc,, +uvicorn/__pycache__/__main__.cpython-37.pyc,, +uvicorn/__pycache__/_subprocess.cpython-37.pyc,, +uvicorn/__pycache__/_types.cpython-37.pyc,, +uvicorn/__pycache__/config.cpython-37.pyc,, +uvicorn/__pycache__/importer.cpython-37.pyc,, +uvicorn/__pycache__/logging.cpython-37.pyc,, +uvicorn/__pycache__/main.cpython-37.pyc,, +uvicorn/__pycache__/server.cpython-37.pyc,, +uvicorn/__pycache__/workers.cpython-37.pyc,, +uvicorn/_subprocess.py,sha256=zip7kqIlWL_GG7dBnl9dVuzScnjDt97VJJNH5PJFcts,2403 +uvicorn/_types.py,sha256=jysk8Dv1S22qgU9P4pVgLz8Xwz7VO61AGCVcCQr4feY,423 +uvicorn/config.py,sha256=xysHliIRVd9_8aDjRqmnLE06I7Z-0wN3Q1te8Hbvfvk,21498 +uvicorn/importer.py,sha256=aGwb0nygYznrjdopDkcmbyWVHXdZAIounPHPEQ245Hk,1166 +uvicorn/lifespan/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/lifespan/__pycache__/__init__.cpython-37.pyc,, +uvicorn/lifespan/__pycache__/off.cpython-37.pyc,, +uvicorn/lifespan/__pycache__/on.cpython-37.pyc,, +uvicorn/lifespan/off.py,sha256=wjwbgYUYHwTUkMQVOt-wnNSSmEvnrrcgvq6tux_xD2o,232 +uvicorn/lifespan/on.py,sha256=jenqzDjiEuZtRPJJEkE0elFApGZkebbT1vcPMKBBbmQ,5192 +uvicorn/logging.py,sha256=kcqf-KVrfukBZznPCJUP6omqUPW44QgYWW_-aLfVxY4,4397 +uvicorn/loops/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/loops/__pycache__/__init__.cpython-37.pyc,, +uvicorn/loops/__pycache__/asyncio.cpython-37.pyc,, +uvicorn/loops/__pycache__/auto.cpython-37.pyc,, +uvicorn/loops/__pycache__/uvloop.cpython-37.pyc,, +uvicorn/loops/asyncio.py,sha256=-SHjygx4KCRGEKaUi6n2GUSlVPWmYzzxssrx5qvkVMg,327 +uvicorn/loops/auto.py,sha256=BWVq18ce9SoFTo3z5zNW2IU2850u2tRrc6WyK7idsdI,400 +uvicorn/loops/uvloop.py,sha256=K4QybYVxtK9C2emDhDPUCkBXR4XMT5Ofv9BPFPoX0ok,148 +uvicorn/main.py,sha256=dsxr1ziEkqUOx67C3WHB3jy39b4AIAMz5wqjWKV3vco,16473 +uvicorn/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/middleware/__pycache__/__init__.cpython-37.pyc,, +uvicorn/middleware/__pycache__/asgi2.cpython-37.pyc,, +uvicorn/middleware/__pycache__/debug.cpython-37.pyc,, +uvicorn/middleware/__pycache__/message_logger.cpython-37.pyc,, +uvicorn/middleware/__pycache__/proxy_headers.cpython-37.pyc,, +uvicorn/middleware/__pycache__/wsgi.cpython-37.pyc,, +uvicorn/middleware/asgi2.py,sha256=Gve5l1W7_IxinJDLEPk5qmwcoCE7awpe0x-d9Kzt4KY,472 +uvicorn/middleware/debug.py,sha256=_pzNEHRBhbzcJDZuD2HzjvzzTLEROgRTBdIkPoR4W-g,3551 +uvicorn/middleware/message_logger.py,sha256=pLhbeiPxeeH_H7okbd5RxS9x9YcluZlcCICKplHhpsY,2925 +uvicorn/middleware/proxy_headers.py,sha256=x5FdQUFTi5-HjwGmsHMMiIqC3XcgFOCf83mbZOmBlGQ,3072 +uvicorn/middleware/wsgi.py,sha256=QeLhPVC8x8IgK5807Rogbe_Me1wNTW5jN1TjDxRoJgA,6718 +uvicorn/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/protocols/__pycache__/__init__.cpython-37.pyc,, +uvicorn/protocols/__pycache__/utils.cpython-37.pyc,, +uvicorn/protocols/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/protocols/http/__pycache__/__init__.cpython-37.pyc,, +uvicorn/protocols/http/__pycache__/auto.cpython-37.pyc,, +uvicorn/protocols/http/__pycache__/flow_control.cpython-37.pyc,, +uvicorn/protocols/http/__pycache__/h11_impl.cpython-37.pyc,, +uvicorn/protocols/http/__pycache__/httptools_impl.cpython-37.pyc,, +uvicorn/protocols/http/auto.py,sha256=fvYmlgqD3ockeVj13Hhjc3kMWBu8zj2D0npUQcvIraM,391 +uvicorn/protocols/http/flow_control.py,sha256=1lgcydIePi59fo8oqNxxe6wqplMrqFbBJ03yQNyBD7U,1844 +uvicorn/protocols/http/h11_impl.py,sha256=15u79j1Sjn4YAVC61ljgyOOCGDrN7-WIU6NGsnLSQtk,20135 +uvicorn/protocols/http/httptools_impl.py,sha256=ZzBIdR0Vjh0F9VES7XK4BWx7qig44-9_XKvFfIF86x0,21095 +uvicorn/protocols/utils.py,sha256=J8pZr9AfKEM7tlsUb-DSSbs0MzmuGrc26rspYcc_Inc,1876 +uvicorn/protocols/websockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/protocols/websockets/__pycache__/__init__.cpython-37.pyc,, +uvicorn/protocols/websockets/__pycache__/auto.cpython-37.pyc,, +uvicorn/protocols/websockets/__pycache__/websockets_impl.cpython-37.pyc,, +uvicorn/protocols/websockets/__pycache__/wsproto_impl.cpython-37.pyc,, +uvicorn/protocols/websockets/auto.py,sha256=Fj-Bufny9Syw9cz0MXzZK4ajGkrTSMg1KvwskfWjuyc,539 +uvicorn/protocols/websockets/websockets_impl.py,sha256=FtKQAr9zes5ybwv2Ge5gdypaCGriFoOFr41ZIfCFo1M,12949 +uvicorn/protocols/websockets/wsproto_impl.py,sha256=uGkxOOuMznB0JRbYcH0VgeqQvjc27QONR4WWnEcK4wo,11967 +uvicorn/server.py,sha256=vXi2tQes1en6BnPygvb5WG99Ly4fGe9Rln2mmli7ttI,10792 +uvicorn/supervisors/__init__.py,sha256=YSH0n2BiqyN5m3QaT_QAkS0DkFE2xXHpKDc4ORbh82o,670 +uvicorn/supervisors/__pycache__/__init__.cpython-37.pyc,, +uvicorn/supervisors/__pycache__/basereload.cpython-37.pyc,, +uvicorn/supervisors/__pycache__/multiprocess.cpython-37.pyc,, +uvicorn/supervisors/__pycache__/statreload.cpython-37.pyc,, +uvicorn/supervisors/__pycache__/watchfilesreload.cpython-37.pyc,, +uvicorn/supervisors/__pycache__/watchgodreload.cpython-37.pyc,, +uvicorn/supervisors/basereload.py,sha256=m2oFWDHdnMZWnAAwuor0RY26N95kmX1wboNZhWeRanw,3341 +uvicorn/supervisors/multiprocess.py,sha256=TdLMy1FxpQp4h7L7wox9n3Qs5KrNrEBxsNZFuM7dOJ0,2231 +uvicorn/supervisors/statreload.py,sha256=p4_6gR9wOWRT6k04DBiwtQl6GINwuKdoTZJz6afArT4,1580 +uvicorn/supervisors/watchfilesreload.py,sha256=5gO3lrPgaC6t8qIWANW2diAXZi8pLLY3NbQlsyxBias,2902 +uvicorn/supervisors/watchgodreload.py,sha256=-htNITwVAcSCBo2ZhVlm_skZ19S7uwiQyrJUfvHKr8c,5491 +uvicorn/workers.py,sha256=g8AGeonUl1xMnjXhxLQ2f7bG1LLfApFE7QhKEa9QYNk,3068 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/REQUESTED b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/WHEEL new file mode 100644 index 00000000..748cda9e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.8.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/entry_points.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/entry_points.txt new file mode 100644 index 00000000..4b00fcb6 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +uvicorn = uvicorn.main:main diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/licenses/LICENSE.md b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/licenses/LICENSE.md new file mode 100644 index 00000000..a6bba145 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn-0.18.3.dist-info/licenses/LICENSE.md @@ -0,0 +1,27 @@ +Copyright © 2017-present, [Encode OSS Ltd](https://www.encode.io/). +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 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__init__.py new file mode 100644 index 00000000..62c740ce --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__init__.py @@ -0,0 +1,5 @@ +from uvicorn.config import Config +from uvicorn.main import Server, main, run + +__version__ = "0.18.3" +__all__ = ["main", "run", "Config", "Server"] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__main__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__main__.py new file mode 100644 index 00000000..8a1dc979 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/__main__.py @@ -0,0 +1,4 @@ +import uvicorn + +if __name__ == "__main__": + uvicorn.main() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_subprocess.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_subprocess.py new file mode 100644 index 00000000..e05473c7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_subprocess.py @@ -0,0 +1,76 @@ +""" +Some light wrappers around Python's multiprocessing, to deal with cleanly +starting child processes. +""" +import multiprocessing +import os +import sys +from multiprocessing.context import SpawnProcess +from socket import socket +from typing import Callable, List, Optional + +from uvicorn.config import Config + +multiprocessing.allow_connection_pickling() +spawn = multiprocessing.get_context("spawn") + + +def get_subprocess( + config: Config, + target: Callable[..., None], + sockets: List[socket], +) -> SpawnProcess: + """ + Called in the parent process, to instantiate a new child process instance. + The child is not yet started at this point. + + * config - The Uvicorn configuration instance. + * target - A callable that accepts a list of sockets. In practice this will + be the `Server.run()` method. + * sockets - A list of sockets to pass to the server. Sockets are bound once + by the parent process, and then passed to the child processes. + """ + # We pass across the stdin fileno, and reopen it in the child process. + # This is required for some debugging environments. + stdin_fileno: Optional[int] + try: + stdin_fileno = sys.stdin.fileno() + except OSError: + stdin_fileno = None + + kwargs = { + "config": config, + "target": target, + "sockets": sockets, + "stdin_fileno": stdin_fileno, + } + + return spawn.Process(target=subprocess_started, kwargs=kwargs) + + +def subprocess_started( + config: Config, + target: Callable[..., None], + sockets: List[socket], + stdin_fileno: Optional[int], +) -> None: + """ + Called when the child process starts. + + * config - The Uvicorn configuration instance. + * target - A callable that accepts a list of sockets. In practice this will + be the `Server.run()` method. + * sockets - A list of sockets to pass to the server. Sockets are bound once + by the parent process, and then passed to the child processes. + * stdin_fileno - The file number of sys.stdin, so that it can be reattached + to the child process. + """ + # Re-open stdin. + if stdin_fileno is not None: + sys.stdin = os.fdopen(stdin_fileno) + + # Logging needs to be setup again for each child. + config.configure_logging() + + # Now we can call into `Server.run(sockets=sockets)` + target(sockets=sockets) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_types.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_types.py new file mode 100644 index 00000000..0a547a50 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/_types.py @@ -0,0 +1,14 @@ +import types +import typing + +# WSGI +Environ = typing.MutableMapping[str, typing.Any] +ExcInfo = typing.Tuple[ + typing.Type[BaseException], BaseException, typing.Optional[types.TracebackType] +] +StartResponse = typing.Callable[ + [str, typing.Iterable[typing.Tuple[str, str]], typing.Optional[ExcInfo]], None +] +WSGIApp = typing.Callable[ + [Environ, StartResponse], typing.Union[typing.Iterable[bytes], BaseException] +] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/config.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/config.py new file mode 100644 index 00000000..3cb6bf3d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/config.py @@ -0,0 +1,591 @@ +import asyncio +import inspect +import json +import logging +import logging.config +import os +import socket +import ssl +import sys +from pathlib import Path +from typing import ( + TYPE_CHECKING, + Any, + Awaitable, + Callable, + Dict, + List, + Optional, + Tuple, + Type, + Union, +) + +from h11._connection import DEFAULT_MAX_INCOMPLETE_EVENT_SIZE + +from uvicorn.logging import TRACE_LOG_LEVEL + +if sys.version_info < (3, 8): # pragma: py-gte-38 + from typing_extensions import Literal +else: # pragma: py-lt-38 + from typing import Literal + +import click + +try: + import yaml +except ImportError: # pragma: no cover + # If the code below that depends on yaml is exercised, it will raise a NameError. + # Install the PyYAML package or the uvicorn[standard] optional dependencies to + # enable this functionality. + pass + +from uvicorn.importer import ImportFromStringError, import_from_string +from uvicorn.middleware.asgi2 import ASGI2Middleware +from uvicorn.middleware.debug import DebugMiddleware +from uvicorn.middleware.message_logger import MessageLoggerMiddleware +from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware +from uvicorn.middleware.wsgi import WSGIMiddleware + +if TYPE_CHECKING: + from asgiref.typing import ASGIApplication + +HTTPProtocolType = Literal["auto", "h11", "httptools"] +WSProtocolType = Literal["auto", "none", "websockets", "wsproto"] +LifespanType = Literal["auto", "on", "off"] +LoopSetupType = Literal["none", "auto", "asyncio", "uvloop"] +InterfaceType = Literal["auto", "asgi3", "asgi2", "wsgi"] + +LOG_LEVELS: Dict[str, int] = { + "critical": logging.CRITICAL, + "error": logging.ERROR, + "warning": logging.WARNING, + "info": logging.INFO, + "debug": logging.DEBUG, + "trace": TRACE_LOG_LEVEL, +} +HTTP_PROTOCOLS: Dict[HTTPProtocolType, str] = { + "auto": "uvicorn.protocols.http.auto:AutoHTTPProtocol", + "h11": "uvicorn.protocols.http.h11_impl:H11Protocol", + "httptools": "uvicorn.protocols.http.httptools_impl:HttpToolsProtocol", +} +WS_PROTOCOLS: Dict[WSProtocolType, Optional[str]] = { + "auto": "uvicorn.protocols.websockets.auto:AutoWebSocketsProtocol", + "none": None, + "websockets": "uvicorn.protocols.websockets.websockets_impl:WebSocketProtocol", + "wsproto": "uvicorn.protocols.websockets.wsproto_impl:WSProtocol", +} +LIFESPAN: Dict[LifespanType, str] = { + "auto": "uvicorn.lifespan.on:LifespanOn", + "on": "uvicorn.lifespan.on:LifespanOn", + "off": "uvicorn.lifespan.off:LifespanOff", +} +LOOP_SETUPS: Dict[LoopSetupType, Optional[str]] = { + "none": None, + "auto": "uvicorn.loops.auto:auto_loop_setup", + "asyncio": "uvicorn.loops.asyncio:asyncio_setup", + "uvloop": "uvicorn.loops.uvloop:uvloop_setup", +} +INTERFACES: List[InterfaceType] = ["auto", "asgi3", "asgi2", "wsgi"] + + +SSL_PROTOCOL_VERSION: int = ssl.PROTOCOL_TLS_SERVER + + +LOGGING_CONFIG: Dict[str, Any] = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "default": { + "()": "uvicorn.logging.DefaultFormatter", + "fmt": "%(levelprefix)s %(message)s", + "use_colors": None, + }, + "access": { + "()": "uvicorn.logging.AccessFormatter", + "fmt": '%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s', # noqa: E501 + }, + }, + "handlers": { + "default": { + "formatter": "default", + "class": "logging.StreamHandler", + "stream": "ext://sys.stderr", + }, + "access": { + "formatter": "access", + "class": "logging.StreamHandler", + "stream": "ext://sys.stdout", + }, + }, + "loggers": { + "uvicorn": {"handlers": ["default"], "level": "INFO"}, + "uvicorn.error": {"level": "INFO"}, + "uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False}, + }, +} + +logger = logging.getLogger("uvicorn.error") + + +def create_ssl_context( + certfile: Union[str, os.PathLike], + keyfile: Optional[Union[str, os.PathLike]], + password: Optional[str], + ssl_version: int, + cert_reqs: int, + ca_certs: Optional[Union[str, os.PathLike]], + ciphers: Optional[str], +) -> ssl.SSLContext: + ctx = ssl.SSLContext(ssl_version) + get_password = (lambda: password) if password else None + ctx.load_cert_chain(certfile, keyfile, get_password) + ctx.verify_mode = ssl.VerifyMode(cert_reqs) + if ca_certs: + ctx.load_verify_locations(ca_certs) + if ciphers: + ctx.set_ciphers(ciphers) + return ctx + + +def is_dir(path: Path) -> bool: + try: + if not path.is_absolute(): + path = path.resolve() + return path.is_dir() + except OSError: + return False + + +def resolve_reload_patterns( + patterns_list: List[str], directories_list: List[str] +) -> Tuple[List[str], List[Path]]: + + directories: List[Path] = list(set(map(Path, directories_list.copy()))) + patterns: List[str] = patterns_list.copy() + + current_working_directory = Path.cwd() + for pattern in patterns_list: + # Special case for the .* pattern, otherwise this would only match + # hidden directories which is probably undesired + if pattern == ".*": + continue + patterns.append(pattern) + if is_dir(Path(pattern)): + directories.append(Path(pattern)) + else: + for match in current_working_directory.glob(pattern): + if is_dir(match): + directories.append(match) + + directories = list(set(directories)) + directories = list(map(Path, directories)) + directories = list(map(lambda x: x.resolve(), directories)) + directories = list( + {reload_path for reload_path in directories if is_dir(reload_path)} + ) + + children = [] + for j in range(len(directories)): + for k in range(j + 1, len(directories)): + if directories[j] in directories[k].parents: + children.append(directories[k]) # pragma: py-darwin + elif directories[k] in directories[j].parents: + children.append(directories[j]) + + directories = list(set(directories).difference(set(children))) + + return list(set(patterns)), directories + + +def _normalize_dirs(dirs: Union[List[str], str, None]) -> List[str]: + if dirs is None: + return [] + if isinstance(dirs, str): + return [dirs] + return list(set(dirs)) + + +class Config: + def __init__( + self, + app: Union["ASGIApplication", Callable, str], + host: str = "127.0.0.1", + port: int = 8000, + uds: Optional[str] = None, + fd: Optional[int] = None, + loop: LoopSetupType = "auto", + http: Union[Type[asyncio.Protocol], HTTPProtocolType] = "auto", + ws: Union[Type[asyncio.Protocol], WSProtocolType] = "auto", + ws_max_size: int = 16 * 1024 * 1024, + ws_ping_interval: Optional[float] = 20.0, + ws_ping_timeout: Optional[float] = 20.0, + ws_per_message_deflate: bool = True, + lifespan: LifespanType = "auto", + env_file: Optional[Union[str, os.PathLike]] = None, + log_config: Optional[Union[Dict[str, Any], str]] = LOGGING_CONFIG, + log_level: Optional[Union[str, int]] = None, + access_log: bool = True, + use_colors: Optional[bool] = None, + interface: InterfaceType = "auto", + debug: bool = False, + reload: bool = False, + reload_dirs: Optional[Union[List[str], str]] = None, + reload_delay: float = 0.25, + reload_includes: Optional[Union[List[str], str]] = None, + reload_excludes: Optional[Union[List[str], str]] = None, + workers: Optional[int] = None, + proxy_headers: bool = True, + server_header: bool = True, + date_header: bool = True, + forwarded_allow_ips: Optional[str] = None, + root_path: str = "", + limit_concurrency: Optional[int] = None, + limit_max_requests: Optional[int] = None, + backlog: int = 2048, + timeout_keep_alive: int = 5, + timeout_notify: int = 30, + callback_notify: Optional[Callable[..., Awaitable[None]]] = None, + ssl_keyfile: Optional[str] = None, + ssl_certfile: Optional[Union[str, os.PathLike]] = None, + ssl_keyfile_password: Optional[str] = None, + ssl_version: int = SSL_PROTOCOL_VERSION, + ssl_cert_reqs: int = ssl.CERT_NONE, + ssl_ca_certs: Optional[str] = None, + ssl_ciphers: str = "TLSv1", + headers: Optional[List[Tuple[str, str]]] = None, + factory: bool = False, + h11_max_incomplete_event_size: int = DEFAULT_MAX_INCOMPLETE_EVENT_SIZE, + ): + self.app = app + self.host = host + self.port = port + self.uds = uds + self.fd = fd + self.loop = loop + self.http = http + self.ws = ws + self.ws_max_size = ws_max_size + self.ws_ping_interval = ws_ping_interval + self.ws_ping_timeout = ws_ping_timeout + self.ws_per_message_deflate = ws_per_message_deflate + self.lifespan = lifespan + self.log_config = log_config + self.log_level = log_level + self.access_log = access_log + self.use_colors = use_colors + self.interface = interface + self.debug = debug + self.reload = reload + self.reload_delay = reload_delay + self.workers = workers or 1 + self.proxy_headers = proxy_headers + self.server_header = server_header + self.date_header = date_header + self.root_path = root_path + self.limit_concurrency = limit_concurrency + self.limit_max_requests = limit_max_requests + self.backlog = backlog + self.timeout_keep_alive = timeout_keep_alive + self.timeout_notify = timeout_notify + self.callback_notify = callback_notify + self.ssl_keyfile = ssl_keyfile + self.ssl_certfile = ssl_certfile + self.ssl_keyfile_password = ssl_keyfile_password + self.ssl_version = ssl_version + self.ssl_cert_reqs = ssl_cert_reqs + self.ssl_ca_certs = ssl_ca_certs + self.ssl_ciphers = ssl_ciphers + self.headers: List[Tuple[str, str]] = headers or [] + self.encoded_headers: List[Tuple[bytes, bytes]] = [] + self.factory = factory + self.h11_max_incomplete_event_size = h11_max_incomplete_event_size + + self.loaded = False + self.configure_logging() + + self.reload_dirs: List[Path] = [] + self.reload_dirs_excludes: List[Path] = [] + self.reload_includes: List[str] = [] + self.reload_excludes: List[str] = [] + + if ( + reload_dirs or reload_includes or reload_excludes + ) and not self.should_reload: + logger.warning( + "Current configuration will not reload as not all conditions are met," + "please refer to documentation." + ) + + if self.should_reload: + reload_dirs = _normalize_dirs(reload_dirs) + reload_includes = _normalize_dirs(reload_includes) + reload_excludes = _normalize_dirs(reload_excludes) + + self.reload_includes, self.reload_dirs = resolve_reload_patterns( + reload_includes, reload_dirs + ) + + self.reload_excludes, self.reload_dirs_excludes = resolve_reload_patterns( + reload_excludes, [] + ) + + reload_dirs_tmp = self.reload_dirs.copy() + + for directory in self.reload_dirs_excludes: + for reload_directory in reload_dirs_tmp: + if ( + directory == reload_directory + or directory in reload_directory.parents + ): + try: + self.reload_dirs.remove(reload_directory) + except ValueError: + pass + + for pattern in self.reload_excludes: + if pattern in self.reload_includes: + self.reload_includes.remove(pattern) + + if not self.reload_dirs: + if reload_dirs: + logger.warning( + "Provided reload directories %s did not contain valid " + + "directories, watching current working directory.", + reload_dirs, + ) + self.reload_dirs = [Path(os.getcwd())] + + logger.info( + "Will watch for changes in these directories: %s", + sorted(list(map(str, self.reload_dirs))), + ) + + if env_file is not None: + from dotenv import load_dotenv + + logger.info("Loading environment from '%s'", env_file) + load_dotenv(dotenv_path=env_file) + + if workers is None and "WEB_CONCURRENCY" in os.environ: + self.workers = int(os.environ["WEB_CONCURRENCY"]) + + if forwarded_allow_ips is None: + self.forwarded_allow_ips = os.environ.get( + "FORWARDED_ALLOW_IPS", "127.0.0.1" + ) + else: + self.forwarded_allow_ips = forwarded_allow_ips + + @property + def asgi_version(self) -> Literal["2.0", "3.0"]: + mapping: Dict[str, Literal["2.0", "3.0"]] = { + "asgi2": "2.0", + "asgi3": "3.0", + "wsgi": "3.0", + } + return mapping[self.interface] + + @property + def is_ssl(self) -> bool: + return bool(self.ssl_keyfile or self.ssl_certfile) + + @property + def use_subprocess(self) -> bool: + return bool(self.reload or self.workers > 1) + + def configure_logging(self) -> None: + logging.addLevelName(TRACE_LOG_LEVEL, "TRACE") + + if self.log_config is not None: + if isinstance(self.log_config, dict): + if self.use_colors in (True, False): + self.log_config["formatters"]["default"][ + "use_colors" + ] = self.use_colors + self.log_config["formatters"]["access"][ + "use_colors" + ] = self.use_colors + logging.config.dictConfig(self.log_config) + elif self.log_config.endswith(".json"): + with open(self.log_config) as file: + loaded_config = json.load(file) + logging.config.dictConfig(loaded_config) + elif self.log_config.endswith((".yaml", ".yml")): + with open(self.log_config) as file: + loaded_config = yaml.safe_load(file) + logging.config.dictConfig(loaded_config) + else: + # See the note about fileConfig() here: + # https://docs.python.org/3/library/logging.config.html#configuration-file-format + logging.config.fileConfig( + self.log_config, disable_existing_loggers=False + ) + + if self.log_level is not None: + if isinstance(self.log_level, str): + log_level = LOG_LEVELS[self.log_level] + else: + log_level = self.log_level + logging.getLogger("uvicorn.error").setLevel(log_level) + logging.getLogger("uvicorn.access").setLevel(log_level) + logging.getLogger("uvicorn.asgi").setLevel(log_level) + if self.access_log is False: + logging.getLogger("uvicorn.access").handlers = [] + logging.getLogger("uvicorn.access").propagate = False + + def load(self) -> None: + assert not self.loaded + + if self.is_ssl: + assert self.ssl_certfile + self.ssl: Optional[ssl.SSLContext] = create_ssl_context( + keyfile=self.ssl_keyfile, + certfile=self.ssl_certfile, + password=self.ssl_keyfile_password, + ssl_version=self.ssl_version, + cert_reqs=self.ssl_cert_reqs, + ca_certs=self.ssl_ca_certs, + ciphers=self.ssl_ciphers, + ) + else: + self.ssl = None + + encoded_headers = [ + (key.lower().encode("latin1"), value.encode("latin1")) + for key, value in self.headers + ] + self.encoded_headers = ( + [(b"server", b"uvicorn")] + encoded_headers + if b"server" not in dict(encoded_headers) and self.server_header + else encoded_headers + ) + + if isinstance(self.http, str): + http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http]) + self.http_protocol_class: Type[asyncio.Protocol] = http_protocol_class + else: + self.http_protocol_class = self.http + + if isinstance(self.ws, str): + ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) + self.ws_protocol_class: Optional[Type[asyncio.Protocol]] = ws_protocol_class + else: + self.ws_protocol_class = self.ws + + self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) + + try: + self.loaded_app = import_from_string(self.app) + except ImportFromStringError as exc: + logger.error("Error loading ASGI app. %s" % exc) + sys.exit(1) + + try: + self.loaded_app = self.loaded_app() + except TypeError as exc: + if self.factory: + logger.error("Error loading ASGI app factory: %s", exc) + sys.exit(1) + else: + if not self.factory: + logger.warning( + "ASGI app factory detected. Using it, " + "but please consider setting the --factory flag explicitly." + ) + + if self.interface == "auto": + if inspect.isclass(self.loaded_app): + use_asgi_3 = hasattr(self.loaded_app, "__await__") + elif inspect.isfunction(self.loaded_app): + use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app) + else: + call = getattr(self.loaded_app, "__call__", None) + use_asgi_3 = asyncio.iscoroutinefunction(call) + self.interface = "asgi3" if use_asgi_3 else "asgi2" + + if self.interface == "wsgi": + self.loaded_app = WSGIMiddleware(self.loaded_app) + self.ws_protocol_class = None + elif self.interface == "asgi2": + self.loaded_app = ASGI2Middleware(self.loaded_app) + + if self.debug: + self.loaded_app = DebugMiddleware(self.loaded_app) + if logger.level <= TRACE_LOG_LEVEL: + self.loaded_app = MessageLoggerMiddleware(self.loaded_app) + if self.proxy_headers: + self.loaded_app = ProxyHeadersMiddleware( + self.loaded_app, trusted_hosts=self.forwarded_allow_ips + ) + + self.loaded = True + + def setup_event_loop(self) -> None: + loop_setup: Optional[Callable] = import_from_string(LOOP_SETUPS[self.loop]) + if loop_setup is not None: + loop_setup(use_subprocess=self.use_subprocess) + + def bind_socket(self) -> socket.socket: + logger_args: List[Union[str, int]] + if self.uds: # pragma: py-win32 + path = self.uds + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + sock.bind(path) + uds_perms = 0o666 + os.chmod(self.uds, uds_perms) + except OSError as exc: + logger.error(exc) + sys.exit(1) + + message = "Uvicorn running on unix socket %s (Press CTRL+C to quit)" + sock_name_format = "%s" + color_message = ( + "Uvicorn running on " + + click.style(sock_name_format, bold=True) + + " (Press CTRL+C to quit)" + ) + logger_args = [self.uds] + elif self.fd: # pragma: py-win32 + sock = socket.fromfd(self.fd, socket.AF_UNIX, socket.SOCK_STREAM) + message = "Uvicorn running on socket %s (Press CTRL+C to quit)" + fd_name_format = "%s" + color_message = ( + "Uvicorn running on " + + click.style(fd_name_format, bold=True) + + " (Press CTRL+C to quit)" + ) + logger_args = [sock.getsockname()] + else: + family = socket.AF_INET + addr_format = "%s://%s:%d" + + if self.host and ":" in self.host: # pragma: py-win32 + # It's an IPv6 address. + family = socket.AF_INET6 + addr_format = "%s://[%s]:%d" + + sock = socket.socket(family=family) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + sock.bind((self.host, self.port)) + except OSError as exc: + logger.error(exc) + sys.exit(1) + + message = f"Uvicorn running on {addr_format} (Press CTRL+C to quit)" + color_message = ( + "Uvicorn running on " + + click.style(addr_format, bold=True) + + " (Press CTRL+C to quit)" + ) + protocol_name = "https" if self.is_ssl else "http" + logger_args = [protocol_name, self.host, self.port] + logger.info(message, *logger_args, extra={"color_message": color_message}) + sock.set_inheritable(True) + return sock + + @property + def should_reload(self) -> bool: + return isinstance(self.app, str) and (self.debug or self.reload) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/importer.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/importer.py new file mode 100644 index 00000000..e612bf13 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/importer.py @@ -0,0 +1,38 @@ +import importlib +from typing import Any + + +class ImportFromStringError(Exception): + pass + + +def import_from_string(import_str: Any) -> Any: + if not isinstance(import_str, str): + return import_str + + module_str, _, attrs_str = import_str.partition(":") + if not module_str or not attrs_str: + message = ( + 'Import string "{import_str}" must be in format ":".' + ) + raise ImportFromStringError(message.format(import_str=import_str)) + + try: + module = importlib.import_module(module_str) + except ImportError as exc: + if exc.name != module_str: + raise exc from None + message = 'Could not import module "{module_str}".' + raise ImportFromStringError(message.format(module_str=module_str)) + + instance = module + try: + for attr_str in attrs_str.split("."): + instance = getattr(instance, attr_str) + except AttributeError: + message = 'Attribute "{attrs_str}" not found in module "{module_str}".' + raise ImportFromStringError( + message.format(attrs_str=attrs_str, module_str=module_str) + ) + + return instance diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/off.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/off.py new file mode 100644 index 00000000..7ec961b5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/off.py @@ -0,0 +1,12 @@ +from uvicorn import Config + + +class LifespanOff: + def __init__(self, config: Config) -> None: + self.should_exit = False + + async def startup(self) -> None: + pass + + async def shutdown(self) -> None: + pass diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/on.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/on.py new file mode 100644 index 00000000..0c650aab --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/lifespan/on.py @@ -0,0 +1,137 @@ +import asyncio +import logging +from asyncio import Queue +from typing import TYPE_CHECKING, Union + +from uvicorn import Config + +if TYPE_CHECKING: + from asgiref.typing import ( + LifespanScope, + LifespanShutdownCompleteEvent, + LifespanShutdownEvent, + LifespanShutdownFailedEvent, + LifespanStartupCompleteEvent, + LifespanStartupEvent, + LifespanStartupFailedEvent, + ) + + LifespanReceiveMessage = Union[LifespanStartupEvent, LifespanShutdownEvent] + LifespanSendMessage = Union[ + LifespanStartupFailedEvent, + LifespanShutdownFailedEvent, + LifespanStartupCompleteEvent, + LifespanShutdownCompleteEvent, + ] + + +STATE_TRANSITION_ERROR = "Got invalid state transition on lifespan protocol." + + +class LifespanOn: + def __init__(self, config: Config) -> None: + if not config.loaded: + config.load() + + self.config = config + self.logger = logging.getLogger("uvicorn.error") + self.startup_event = asyncio.Event() + self.shutdown_event = asyncio.Event() + self.receive_queue: "Queue[LifespanReceiveMessage]" = asyncio.Queue() + self.error_occured = False + self.startup_failed = False + self.shutdown_failed = False + self.should_exit = False + + async def startup(self) -> None: + self.logger.info("Waiting for application startup.") + + loop = asyncio.get_event_loop() + main_lifespan_task = loop.create_task(self.main()) # noqa: F841 + # Keep a hard reference to prevent garbage collection + # See https://github.com/encode/uvicorn/pull/972 + startup_event: LifespanStartupEvent = {"type": "lifespan.startup"} + await self.receive_queue.put(startup_event) + await self.startup_event.wait() + + if self.startup_failed or (self.error_occured and self.config.lifespan == "on"): + self.logger.error("Application startup failed. Exiting.") + self.should_exit = True + else: + self.logger.info("Application startup complete.") + + async def shutdown(self) -> None: + if self.error_occured: + return + self.logger.info("Waiting for application shutdown.") + shutdown_event: LifespanShutdownEvent = {"type": "lifespan.shutdown"} + await self.receive_queue.put(shutdown_event) + await self.shutdown_event.wait() + + if self.shutdown_failed or ( + self.error_occured and self.config.lifespan == "on" + ): + self.logger.error("Application shutdown failed. Exiting.") + self.should_exit = True + else: + self.logger.info("Application shutdown complete.") + + async def main(self) -> None: + try: + app = self.config.loaded_app + scope: LifespanScope = { + "type": "lifespan", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.0"}, + } + await app(scope, self.receive, self.send) + except BaseException as exc: + self.asgi = None + self.error_occured = True + if self.startup_failed or self.shutdown_failed: + return + if self.config.lifespan == "auto": + msg = "ASGI 'lifespan' protocol appears unsupported." + self.logger.info(msg) + else: + msg = "Exception in 'lifespan' protocol\n" + self.logger.error(msg, exc_info=exc) + finally: + self.startup_event.set() + self.shutdown_event.set() + + async def send(self, message: "LifespanSendMessage") -> None: + assert message["type"] in ( + "lifespan.startup.complete", + "lifespan.startup.failed", + "lifespan.shutdown.complete", + "lifespan.shutdown.failed", + ) + + if message["type"] == "lifespan.startup.complete": + assert not self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.startup_event.set() + + elif message["type"] == "lifespan.startup.failed": + assert not self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.startup_event.set() + self.startup_failed = True + if message.get("message"): + self.logger.error(message["message"]) + + elif message["type"] == "lifespan.shutdown.complete": + assert self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.shutdown_event.set() + + elif message["type"] == "lifespan.shutdown.failed": + assert self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.shutdown_event.set() + self.shutdown_failed = True + if message.get("message"): + self.logger.error(message["message"]) + + async def receive(self) -> "LifespanReceiveMessage": + return await self.receive_queue.get() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/logging.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/logging.py new file mode 100644 index 00000000..b12a710d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/logging.py @@ -0,0 +1,122 @@ +import http +import logging +import sys +from copy import copy +from typing import Optional + +import click + +if sys.version_info < (3, 8): # pragma: py-gte-38 + from typing_extensions import Literal +else: # pragma: py-lt-38 + from typing import Literal + +TRACE_LOG_LEVEL = 5 + + +class ColourizedFormatter(logging.Formatter): + """ + A custom log formatter class that: + + * Outputs the LOG_LEVEL with an appropriate color. + * If a log call includes an `extras={"color_message": ...}` it will be used + for formatting the output, instead of the plain text message. + """ + + level_name_colors = { + TRACE_LOG_LEVEL: lambda level_name: click.style(str(level_name), fg="blue"), + logging.DEBUG: lambda level_name: click.style(str(level_name), fg="cyan"), + logging.INFO: lambda level_name: click.style(str(level_name), fg="green"), + logging.WARNING: lambda level_name: click.style(str(level_name), fg="yellow"), + logging.ERROR: lambda level_name: click.style(str(level_name), fg="red"), + logging.CRITICAL: lambda level_name: click.style( + str(level_name), fg="bright_red" + ), + } + + def __init__( + self, + fmt: Optional[str] = None, + datefmt: Optional[str] = None, + style: Literal["%", "{", "$"] = "%", + use_colors: Optional[bool] = None, + ): + if use_colors in (True, False): + self.use_colors = use_colors + else: + self.use_colors = sys.stdout.isatty() + super().__init__(fmt=fmt, datefmt=datefmt, style=style) + + def color_level_name(self, level_name: str, level_no: int) -> str: + def default(level_name: str) -> str: + return str(level_name) # pragma: no cover + + func = self.level_name_colors.get(level_no, default) + return func(level_name) + + def should_use_colors(self) -> bool: + return True # pragma: no cover + + def formatMessage(self, record: logging.LogRecord) -> str: + recordcopy = copy(record) + levelname = recordcopy.levelname + seperator = " " * (8 - len(recordcopy.levelname)) + if self.use_colors: + levelname = self.color_level_name(levelname, recordcopy.levelno) + if "color_message" in recordcopy.__dict__: + recordcopy.msg = recordcopy.__dict__["color_message"] + recordcopy.__dict__["message"] = recordcopy.getMessage() + recordcopy.__dict__["levelprefix"] = levelname + ":" + seperator + return super().formatMessage(recordcopy) + + +class DefaultFormatter(ColourizedFormatter): + def should_use_colors(self) -> bool: + return sys.stderr.isatty() # pragma: no cover + + +class AccessFormatter(ColourizedFormatter): + status_code_colours = { + 1: lambda code: click.style(str(code), fg="bright_white"), + 2: lambda code: click.style(str(code), fg="green"), + 3: lambda code: click.style(str(code), fg="yellow"), + 4: lambda code: click.style(str(code), fg="red"), + 5: lambda code: click.style(str(code), fg="bright_red"), + } + + def get_status_code(self, status_code: int) -> str: + try: + status_phrase = http.HTTPStatus(status_code).phrase + except ValueError: + status_phrase = "" + status_and_phrase = "%s %s" % (status_code, status_phrase) + if self.use_colors: + + def default(code: int) -> str: + return status_and_phrase # pragma: no cover + + func = self.status_code_colours.get(status_code // 100, default) + return func(status_and_phrase) + return status_and_phrase + + def formatMessage(self, record: logging.LogRecord) -> str: + recordcopy = copy(record) + ( + client_addr, + method, + full_path, + http_version, + status_code, + ) = recordcopy.args # type: ignore[misc] + status_code = self.get_status_code(int(status_code)) # type: ignore[arg-type] + request_line = "%s %s HTTP/%s" % (method, full_path, http_version) + if self.use_colors: + request_line = click.style(request_line, bold=True) + recordcopy.__dict__.update( + { + "client_addr": client_addr, + "request_line": request_line, + "status_code": status_code, + } + ) + return super().formatMessage(recordcopy) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/asyncio.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/asyncio.py new file mode 100644 index 00000000..867545f2 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/asyncio.py @@ -0,0 +1,10 @@ +import asyncio +import logging +import sys + +logger = logging.getLogger("uvicorn.error") + + +def asyncio_setup(use_subprocess: bool = False) -> None: # pragma: no cover + if sys.version_info >= (3, 8) and sys.platform == "win32" and use_subprocess: + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/auto.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/auto.py new file mode 100644 index 00000000..2285457b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/auto.py @@ -0,0 +1,11 @@ +def auto_loop_setup(use_subprocess: bool = False) -> None: + try: + import uvloop # noqa + except ImportError: # pragma: no cover + from uvicorn.loops.asyncio import asyncio_setup as loop_setup + + loop_setup(use_subprocess=use_subprocess) + else: # pragma: no cover + from uvicorn.loops.uvloop import uvloop_setup + + uvloop_setup(use_subprocess=use_subprocess) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/uvloop.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/uvloop.py new file mode 100644 index 00000000..0e2fd1eb --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/loops/uvloop.py @@ -0,0 +1,7 @@ +import asyncio + +import uvloop + + +def uvloop_setup(use_subprocess: bool = False) -> None: + asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/main.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/main.py new file mode 100644 index 00000000..f4318ee6 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/main.py @@ -0,0 +1,585 @@ +import asyncio +import logging +import os +import platform +import ssl +import sys +import typing + +import click +from h11._connection import DEFAULT_MAX_INCOMPLETE_EVENT_SIZE + +import uvicorn +from uvicorn.config import ( + HTTP_PROTOCOLS, + INTERFACES, + LIFESPAN, + LOG_LEVELS, + LOGGING_CONFIG, + LOOP_SETUPS, + SSL_PROTOCOL_VERSION, + WS_PROTOCOLS, + Config, + HTTPProtocolType, + InterfaceType, + LifespanType, + LoopSetupType, + WSProtocolType, +) +from uvicorn.server import Server, ServerState # noqa: F401 # Used to be defined here. +from uvicorn.supervisors import ChangeReload, Multiprocess + +if typing.TYPE_CHECKING: + from asgiref.typing import ASGIApplication + +LEVEL_CHOICES = click.Choice(list(LOG_LEVELS.keys())) +HTTP_CHOICES = click.Choice(list(HTTP_PROTOCOLS.keys())) +WS_CHOICES = click.Choice(list(WS_PROTOCOLS.keys())) +LIFESPAN_CHOICES = click.Choice(list(LIFESPAN.keys())) +LOOP_CHOICES = click.Choice([key for key in LOOP_SETUPS.keys() if key != "none"]) +INTERFACE_CHOICES = click.Choice(INTERFACES) + +STARTUP_FAILURE = 3 + +logger = logging.getLogger("uvicorn.error") + + +def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + click.echo( + "Running uvicorn %s with %s %s on %s" + % ( + uvicorn.__version__, + platform.python_implementation(), + platform.python_version(), + platform.system(), + ) + ) + ctx.exit() + + +@click.command(context_settings={"auto_envvar_prefix": "UVICORN"}) +@click.argument("app") +@click.option( + "--host", + type=str, + default="127.0.0.1", + help="Bind socket to this host.", + show_default=True, +) +@click.option( + "--port", + type=int, + default=8000, + help="Bind socket to this port.", + show_default=True, +) +@click.option("--uds", type=str, default=None, help="Bind to a UNIX domain socket.") +@click.option( + "--fd", type=int, default=None, help="Bind to socket from this file descriptor." +) +@click.option( + "--debug", is_flag=True, default=False, help="Enable debug mode.", hidden=True +) +@click.option("--reload", is_flag=True, default=False, help="Enable auto-reload.") +@click.option( + "--reload-dir", + "reload_dirs", + multiple=True, + help="Set reload directories explicitly, instead of using the current working" + " directory.", + type=click.Path(exists=True), +) +@click.option( + "--reload-include", + "reload_includes", + multiple=True, + help="Set glob patterns to include while watching for files. Includes '*.py' " + "by default; these defaults can be overridden with `--reload-exclude`. " + "This option has no effect unless watchfiles is installed.", +) +@click.option( + "--reload-exclude", + "reload_excludes", + multiple=True, + help="Set glob patterns to exclude while watching for files. Includes " + "'.*, .py[cod], .sw.*, ~*' by default; these defaults can be overridden " + "with `--reload-include`. This option has no effect unless watchfiles is " + "installed.", +) +@click.option( + "--reload-delay", + type=float, + default=0.25, + show_default=True, + help="Delay between previous and next check if application needs to be." + " Defaults to 0.25s.", +) +@click.option( + "--workers", + default=None, + type=int, + help="Number of worker processes. Defaults to the $WEB_CONCURRENCY environment" + " variable if available, or 1. Not valid with --reload.", +) +@click.option( + "--loop", + type=LOOP_CHOICES, + default="auto", + help="Event loop implementation.", + show_default=True, +) +@click.option( + "--http", + type=HTTP_CHOICES, + default="auto", + help="HTTP protocol implementation.", + show_default=True, +) +@click.option( + "--ws", + type=WS_CHOICES, + default="auto", + help="WebSocket protocol implementation.", + show_default=True, +) +@click.option( + "--ws-max-size", + type=int, + default=16777216, + help="WebSocket max size message in bytes", + show_default=True, +) +@click.option( + "--ws-ping-interval", + type=float, + default=20.0, + help="WebSocket ping interval", + show_default=True, +) +@click.option( + "--ws-ping-timeout", + type=float, + default=20.0, + help="WebSocket ping timeout", + show_default=True, +) +@click.option( + "--ws-per-message-deflate", + type=bool, + default=True, + help="WebSocket per-message-deflate compression", + show_default=True, +) +@click.option( + "--lifespan", + type=LIFESPAN_CHOICES, + default="auto", + help="Lifespan implementation.", + show_default=True, +) +@click.option( + "--interface", + type=INTERFACE_CHOICES, + default="auto", + help="Select ASGI3, ASGI2, or WSGI as the application interface.", + show_default=True, +) +@click.option( + "--env-file", + type=click.Path(exists=True), + default=None, + help="Environment configuration file.", + show_default=True, +) +@click.option( + "--log-config", + type=click.Path(exists=True), + default=None, + help="Logging configuration file. Supported formats: .ini, .json, .yaml.", + show_default=True, +) +@click.option( + "--log-level", + type=LEVEL_CHOICES, + default=None, + help="Log level. [default: info]", + show_default=True, +) +@click.option( + "--access-log/--no-access-log", + is_flag=True, + default=True, + help="Enable/Disable access log.", +) +@click.option( + "--use-colors/--no-use-colors", + is_flag=True, + default=None, + help="Enable/Disable colorized logging.", +) +@click.option( + "--proxy-headers/--no-proxy-headers", + is_flag=True, + default=True, + help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to " + "populate remote address info.", +) +@click.option( + "--server-header/--no-server-header", + is_flag=True, + default=True, + help="Enable/Disable default Server header.", +) +@click.option( + "--date-header/--no-date-header", + is_flag=True, + default=True, + help="Enable/Disable default Date header.", +) +@click.option( + "--forwarded-allow-ips", + type=str, + default=None, + help="Comma separated list of IPs to trust with proxy headers. Defaults to" + " the $FORWARDED_ALLOW_IPS environment variable if available, or '127.0.0.1'.", +) +@click.option( + "--root-path", + type=str, + default="", + help="Set the ASGI 'root_path' for applications submounted below a given URL path.", +) +@click.option( + "--limit-concurrency", + type=int, + default=None, + help="Maximum number of concurrent connections or tasks to allow, before issuing" + " HTTP 503 responses.", +) +@click.option( + "--backlog", + type=int, + default=2048, + help="Maximum number of connections to hold in backlog", +) +@click.option( + "--limit-max-requests", + type=int, + default=None, + help="Maximum number of requests to service before terminating the process.", +) +@click.option( + "--timeout-keep-alive", + type=int, + default=5, + help="Close Keep-Alive connections if no new data is received within this timeout.", + show_default=True, +) +@click.option( + "--ssl-keyfile", type=str, default=None, help="SSL key file", show_default=True +) +@click.option( + "--ssl-certfile", + type=str, + default=None, + help="SSL certificate file", + show_default=True, +) +@click.option( + "--ssl-keyfile-password", + type=str, + default=None, + help="SSL keyfile password", + show_default=True, +) +@click.option( + "--ssl-version", + type=int, + default=int(SSL_PROTOCOL_VERSION), + help="SSL version to use (see stdlib ssl module's)", + show_default=True, +) +@click.option( + "--ssl-cert-reqs", + type=int, + default=int(ssl.CERT_NONE), + help="Whether client certificate is required (see stdlib ssl module's)", + show_default=True, +) +@click.option( + "--ssl-ca-certs", + type=str, + default=None, + help="CA certificates file", + show_default=True, +) +@click.option( + "--ssl-ciphers", + type=str, + default="TLSv1", + help="Ciphers to use (see stdlib ssl module's)", + show_default=True, +) +@click.option( + "--header", + "headers", + multiple=True, + help="Specify custom default HTTP response headers as a Name:Value pair", +) +@click.option( + "--version", + is_flag=True, + callback=print_version, + expose_value=False, + is_eager=True, + help="Display the uvicorn version and exit.", +) +@click.option( + "--app-dir", + default=".", + show_default=True, + help="Look for APP in the specified directory, by adding this to the PYTHONPATH." + " Defaults to the current working directory.", +) +@click.option( + "--h11-max-incomplete-event-size", + "h11_max_incomplete_event_size", + type=int, + default=DEFAULT_MAX_INCOMPLETE_EVENT_SIZE, + help="For h11, the maximum number of bytes to buffer of an incomplete event.", +) +@click.option( + "--factory", + is_flag=True, + default=False, + help="Treat APP as an application factory, i.e. a () -> callable.", + show_default=True, +) +def main( + app: str, + host: str, + port: int, + uds: str, + fd: int, + loop: LoopSetupType, + http: HTTPProtocolType, + ws: WSProtocolType, + ws_max_size: int, + ws_ping_interval: float, + ws_ping_timeout: float, + ws_per_message_deflate: bool, + lifespan: LifespanType, + interface: InterfaceType, + debug: bool, + reload: bool, + reload_dirs: typing.List[str], + reload_includes: typing.List[str], + reload_excludes: typing.List[str], + reload_delay: float, + workers: int, + env_file: str, + log_config: str, + log_level: str, + access_log: bool, + proxy_headers: bool, + server_header: bool, + date_header: bool, + forwarded_allow_ips: str, + root_path: str, + limit_concurrency: int, + backlog: int, + limit_max_requests: int, + timeout_keep_alive: int, + ssl_keyfile: str, + ssl_certfile: str, + ssl_keyfile_password: str, + ssl_version: int, + ssl_cert_reqs: int, + ssl_ca_certs: str, + ssl_ciphers: str, + headers: typing.List[str], + use_colors: bool, + app_dir: str, + h11_max_incomplete_event_size: int, + factory: bool, +) -> None: + run( + app, + host=host, + port=port, + uds=uds, + fd=fd, + loop=loop, + http=http, + ws=ws, + ws_max_size=ws_max_size, + ws_ping_interval=ws_ping_interval, + ws_ping_timeout=ws_ping_timeout, + ws_per_message_deflate=ws_per_message_deflate, + lifespan=lifespan, + env_file=env_file, + log_config=LOGGING_CONFIG if log_config is None else log_config, + log_level=log_level, + access_log=access_log, + interface=interface, + debug=debug, + reload=reload, + reload_dirs=reload_dirs or None, + reload_includes=reload_includes or None, + reload_excludes=reload_excludes or None, + reload_delay=reload_delay, + workers=workers, + proxy_headers=proxy_headers, + server_header=server_header, + date_header=date_header, + forwarded_allow_ips=forwarded_allow_ips, + root_path=root_path, + limit_concurrency=limit_concurrency, + backlog=backlog, + limit_max_requests=limit_max_requests, + timeout_keep_alive=timeout_keep_alive, + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + ssl_keyfile_password=ssl_keyfile_password, + ssl_version=ssl_version, + ssl_cert_reqs=ssl_cert_reqs, + ssl_ca_certs=ssl_ca_certs, + ssl_ciphers=ssl_ciphers, + headers=[header.split(":", 1) for header in headers], # type: ignore[misc] + use_colors=use_colors, + factory=factory, + app_dir=app_dir, + h11_max_incomplete_event_size=h11_max_incomplete_event_size, + ) + + +def run( + app: typing.Union["ASGIApplication", typing.Callable, str], + *, + host: str = "127.0.0.1", + port: int = 8000, + uds: typing.Optional[str] = None, + fd: typing.Optional[int] = None, + loop: LoopSetupType = "auto", + http: typing.Union[typing.Type[asyncio.Protocol], HTTPProtocolType] = "auto", + ws: typing.Union[typing.Type[asyncio.Protocol], WSProtocolType] = "auto", + ws_max_size: int = 16777216, + ws_ping_interval: typing.Optional[float] = 20.0, + ws_ping_timeout: typing.Optional[float] = 20.0, + ws_per_message_deflate: bool = True, + lifespan: LifespanType = "auto", + interface: InterfaceType = "auto", + debug: bool = False, + reload: bool = False, + reload_dirs: typing.Optional[typing.Union[typing.List[str], str]] = None, + reload_includes: typing.Optional[typing.Union[typing.List[str], str]] = None, + reload_excludes: typing.Optional[typing.Union[typing.List[str], str]] = None, + reload_delay: float = 0.25, + workers: typing.Optional[int] = None, + env_file: typing.Optional[typing.Union[str, os.PathLike]] = None, + log_config: typing.Optional[ + typing.Union[typing.Dict[str, typing.Any], str] + ] = LOGGING_CONFIG, + log_level: typing.Optional[typing.Union[str, int]] = None, + access_log: bool = True, + proxy_headers: bool = True, + server_header: bool = True, + date_header: bool = True, + forwarded_allow_ips: typing.Optional[str] = None, + root_path: str = "", + limit_concurrency: typing.Optional[int] = None, + backlog: int = 2048, + limit_max_requests: typing.Optional[int] = None, + timeout_keep_alive: int = 5, + ssl_keyfile: typing.Optional[str] = None, + ssl_certfile: typing.Optional[typing.Union[str, os.PathLike]] = None, + ssl_keyfile_password: typing.Optional[str] = None, + ssl_version: int = SSL_PROTOCOL_VERSION, + ssl_cert_reqs: int = ssl.CERT_NONE, + ssl_ca_certs: typing.Optional[str] = None, + ssl_ciphers: str = "TLSv1", + headers: typing.Optional[typing.List[typing.Tuple[str, str]]] = None, + use_colors: typing.Optional[bool] = None, + app_dir: typing.Optional[str] = None, + factory: bool = False, + h11_max_incomplete_event_size: int = DEFAULT_MAX_INCOMPLETE_EVENT_SIZE, +) -> None: + if app_dir is not None: + sys.path.insert(0, app_dir) + + config = Config( + app, + host=host, + port=port, + uds=uds, + fd=fd, + loop=loop, + http=http, + ws=ws, + ws_max_size=ws_max_size, + ws_ping_interval=ws_ping_interval, + ws_ping_timeout=ws_ping_timeout, + ws_per_message_deflate=ws_per_message_deflate, + lifespan=lifespan, + interface=interface, + debug=debug, + reload=reload, + reload_dirs=reload_dirs, + reload_includes=reload_includes, + reload_excludes=reload_excludes, + reload_delay=reload_delay, + workers=workers, + env_file=env_file, + log_config=log_config, + log_level=log_level, + access_log=access_log, + proxy_headers=proxy_headers, + server_header=server_header, + date_header=date_header, + forwarded_allow_ips=forwarded_allow_ips, + root_path=root_path, + limit_concurrency=limit_concurrency, + backlog=backlog, + limit_max_requests=limit_max_requests, + timeout_keep_alive=timeout_keep_alive, + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + ssl_keyfile_password=ssl_keyfile_password, + ssl_version=ssl_version, + ssl_cert_reqs=ssl_cert_reqs, + ssl_ca_certs=ssl_ca_certs, + ssl_ciphers=ssl_ciphers, + headers=headers, + use_colors=use_colors, + factory=factory, + h11_max_incomplete_event_size=h11_max_incomplete_event_size, + ) + server = Server(config=config) + + if (config.reload or config.workers > 1) and not isinstance(app, str): + logger = logging.getLogger("uvicorn.error") + logger.warning( + "You must pass the application as an import string to enable 'reload' or " + "'workers'." + ) + sys.exit(1) + + if config.should_reload: + sock = config.bind_socket() + ChangeReload(config, target=server.run, sockets=[sock]).run() + elif config.workers > 1: + sock = config.bind_socket() + Multiprocess(config, target=server.run, sockets=[sock]).run() + else: + server.run() + if config.uds: + os.remove(config.uds) # pragma: py-win32 + + if not server.started and not config.should_reload and config.workers == 1: + sys.exit(STARTUP_FAILURE) + + +if __name__ == "__main__": + main() # pragma: no cover diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/asgi2.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/asgi2.py new file mode 100644 index 00000000..c92b6c8f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/asgi2.py @@ -0,0 +1,20 @@ +import typing + +if typing.TYPE_CHECKING: + from asgiref.typing import ( + ASGI2Application, + ASGIReceiveCallable, + ASGISendCallable, + Scope, + ) + + +class ASGI2Middleware: + def __init__(self, app: "ASGI2Application"): + self.app = app + + async def __call__( + self, scope: "Scope", receive: "ASGIReceiveCallable", send: "ASGISendCallable" + ) -> None: + instance = self.app(scope) + await instance(receive, send) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/debug.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/debug.py new file mode 100644 index 00000000..f94b5f67 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/debug.py @@ -0,0 +1,122 @@ +import html +import traceback +from typing import TYPE_CHECKING, Union + +if TYPE_CHECKING: + from asgiref.typing import ( + ASGI3Application, + ASGIReceiveCallable, + ASGISendCallable, + ASGISendEvent, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + WWWScope, + ) + + +class HTMLResponse: + def __init__(self, content: str, status_code: int): + self.content = content + self.status_code = status_code + + async def __call__( + self, + scope: "WWWScope", + receive: "ASGIReceiveCallable", + send: "ASGISendCallable", + ) -> None: + response_start: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": self.status_code, + "headers": [(b"content-type", b"text/html; charset=utf-8")], + } + await send(response_start) + + response_body: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": self.content.encode("utf-8"), + "more_body": False, + } + await send(response_body) + + +class PlainTextResponse: + def __init__(self, content: str, status_code: int): + self.content = content + self.status_code = status_code + + async def __call__( + self, + scope: "WWWScope", + receive: "ASGIReceiveCallable", + send: "ASGISendCallable", + ) -> None: + response_start: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": self.status_code, + "headers": [(b"content-type", b"text/plain; charset=utf-8")], + } + await send(response_start) + + response_body: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": self.content.encode("utf-8"), + "more_body": False, + } + await send(response_body) + + +def get_accept_header(scope: "WWWScope") -> str: + accept = "*/*" + + for key, value in scope.get("headers", []): + if key == b"accept": + accept = value.decode("ascii") + break + + return accept + + +class DebugMiddleware: + def __init__(self, app: "ASGI3Application"): + self.app = app + + async def __call__( + self, + scope: "WWWScope", + receive: "ASGIReceiveCallable", + send: "ASGISendCallable", + ) -> None: + if scope["type"] != "http": + return await self.app(scope, receive, send) + + response_started = False + + async def inner_send(message: "ASGISendEvent") -> None: + nonlocal response_started, send + + if message["type"] == "http.response.start": + response_started = True + await send(message) + + try: + await self.app(scope, receive, inner_send) + except BaseException as exc: + if response_started: + raise exc from None + + accept = get_accept_header(scope) + response: Union[HTMLResponse, PlainTextResponse] + if "text/html" in accept: + exc_html = html.escape(traceback.format_exc()) + content = ( + "

      500 Server Error

      %s
      " + % exc_html + ) + response = HTMLResponse(content, status_code=500) + else: + content = traceback.format_exc() + response = PlainTextResponse(content, status_code=500) + + await response(scope, receive, send) + raise exc from None diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/message_logger.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/message_logger.py new file mode 100644 index 00000000..e3d7a572 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/message_logger.py @@ -0,0 +1,89 @@ +import logging +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from asgiref.typing import ( + ASGI3Application, + ASGIReceiveCallable, + ASGIReceiveEvent, + ASGISendCallable, + ASGISendEvent, + WWWScope, + ) + +from uvicorn.logging import TRACE_LOG_LEVEL + +PLACEHOLDER_FORMAT = { + "body": "<{length} bytes>", + "bytes": "<{length} bytes>", + "text": "<{length} chars>", + "headers": "<...>", +} + + +def message_with_placeholders(message: Any) -> Any: + """ + Return an ASGI message, with any body-type content omitted and replaced + with a placeholder. + """ + new_message = message.copy() + for attr in PLACEHOLDER_FORMAT.keys(): + if message.get(attr) is not None: + content = message[attr] + placeholder = PLACEHOLDER_FORMAT[attr].format(length=len(content)) + new_message[attr] = placeholder + return new_message + + +class MessageLoggerMiddleware: + def __init__(self, app: "ASGI3Application"): + self.task_counter = 0 + self.app = app + self.logger = logging.getLogger("uvicorn.asgi") + + def trace(message: Any, *args: Any, **kwargs: Any) -> None: + self.logger.log(TRACE_LOG_LEVEL, message, *args, **kwargs) + + self.logger.trace = trace # type: ignore + + async def __call__( + self, + scope: "WWWScope", + receive: "ASGIReceiveCallable", + send: "ASGISendCallable", + ) -> None: + self.task_counter += 1 + + task_counter = self.task_counter + client = scope.get("client") + prefix = "%s:%d - ASGI" % (client[0], client[1]) if client else "ASGI" + + async def inner_receive() -> "ASGIReceiveEvent": + message = await receive() + logged_message = message_with_placeholders(message) + log_text = "%s [%d] Receive %s" + self.logger.trace( # type: ignore + log_text, prefix, task_counter, logged_message + ) + return message + + async def inner_send(message: "ASGISendEvent") -> None: + logged_message = message_with_placeholders(message) + log_text = "%s [%d] Send %s" + self.logger.trace( # type: ignore + log_text, prefix, task_counter, logged_message + ) + await send(message) + + logged_scope = message_with_placeholders(scope) + log_text = "%s [%d] Started scope=%s" + self.logger.trace(log_text, prefix, task_counter, logged_scope) # type: ignore + try: + await self.app(scope, inner_receive, inner_send) + except BaseException as exc: + log_text = "%s [%d] Raised exception" + self.logger.trace(log_text, prefix, task_counter) # type: ignore + raise exc from None + else: + log_text = "%s [%d] Completed" + self.logger.trace(log_text, prefix, task_counter) # type: ignore diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/proxy_headers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/proxy_headers.py new file mode 100644 index 00000000..4b62cf20 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/proxy_headers.py @@ -0,0 +1,78 @@ +""" +This middleware can be used when a known proxy is fronting the application, +and is trusted to be properly setting the `X-Forwarded-Proto` and +`X-Forwarded-For` headers with the connecting client information. + +Modifies the `client` and `scheme` information so that they reference +the connecting client, rather that the connecting proxy. + +https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies +""" +from typing import TYPE_CHECKING, List, Optional, Tuple, Union, cast + +if TYPE_CHECKING: + from asgiref.typing import ( + ASGI3Application, + ASGIReceiveCallable, + ASGISendCallable, + HTTPScope, + Scope, + WebSocketScope, + ) + + +class ProxyHeadersMiddleware: + def __init__( + self, + app: "ASGI3Application", + trusted_hosts: Union[List[str], str] = "127.0.0.1", + ) -> None: + self.app = app + if isinstance(trusted_hosts, str): + self.trusted_hosts = {item.strip() for item in trusted_hosts.split(",")} + else: + self.trusted_hosts = set(trusted_hosts) + self.always_trust = "*" in self.trusted_hosts + + def get_trusted_client_host( + self, x_forwarded_for_hosts: List[str] + ) -> Optional[str]: + if self.always_trust: + return x_forwarded_for_hosts[0] + + for host in reversed(x_forwarded_for_hosts): + if host not in self.trusted_hosts: + return host + + return None + + async def __call__( + self, scope: "Scope", receive: "ASGIReceiveCallable", send: "ASGISendCallable" + ) -> None: + if scope["type"] in ("http", "websocket"): + scope = cast(Union["HTTPScope", "WebSocketScope"], scope) + client_addr: Optional[Tuple[str, int]] = scope.get("client") + client_host = client_addr[0] if client_addr else None + + if self.always_trust or client_host in self.trusted_hosts: + headers = dict(scope["headers"]) + + if b"x-forwarded-proto" in headers: + # Determine if the incoming request was http or https based on + # the X-Forwarded-Proto header. + x_forwarded_proto = headers[b"x-forwarded-proto"].decode("latin1") + scope["scheme"] = x_forwarded_proto.strip() # type: ignore[index] + + if b"x-forwarded-for" in headers: + # Determine the client address from the last trusted IP in the + # X-Forwarded-For header. We've lost the connecting client's port + # information by now, so only include the host. + x_forwarded_for = headers[b"x-forwarded-for"].decode("latin1") + x_forwarded_for_hosts = [ + item.strip() for item in x_forwarded_for.split(",") + ] + host = self.get_trusted_client_host(x_forwarded_for_hosts) + port = 0 + scope["client"] = (host, port) # type: ignore[arg-type] + + return await self.app(scope, receive, send) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/wsgi.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/wsgi.py new file mode 100644 index 00000000..9a79a3ba --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/middleware/wsgi.py @@ -0,0 +1,190 @@ +import asyncio +import concurrent.futures +import io +import sys +from collections import deque +from typing import TYPE_CHECKING, Deque, Iterable, Optional, Tuple + +if TYPE_CHECKING: + from asgiref.typing import ( + ASGIReceiveCallable, + ASGIReceiveEvent, + ASGISendCallable, + ASGISendEvent, + HTTPRequestEvent, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + HTTPScope, + ) + +from uvicorn._types import Environ, ExcInfo, StartResponse, WSGIApp + + +def build_environ( + scope: "HTTPScope", message: "ASGIReceiveEvent", body: io.BytesIO +) -> Environ: + """ + Builds a scope and request message into a WSGI environ object. + """ + environ = { + "REQUEST_METHOD": scope["method"], + "SCRIPT_NAME": "", + "PATH_INFO": scope["path"].encode("utf8").decode("latin1"), + "QUERY_STRING": scope["query_string"].decode("ascii"), + "SERVER_PROTOCOL": "HTTP/%s" % scope["http_version"], + "wsgi.version": (1, 0), + "wsgi.url_scheme": scope.get("scheme", "http"), + "wsgi.input": body, + "wsgi.errors": sys.stdout, + "wsgi.multithread": True, + "wsgi.multiprocess": True, + "wsgi.run_once": False, + } + + # Get server name and port - required in WSGI, not in ASGI + server = scope.get("server") + if server is None: + server = ("localhost", 80) + environ["SERVER_NAME"] = server[0] + environ["SERVER_PORT"] = server[1] + + # Get client IP address + client = scope.get("client") + if client is not None: + environ["REMOTE_ADDR"] = client[0] + + # Go through headers and make them into environ entries + for name, value in scope.get("headers", []): + name_str: str = name.decode("latin1") + if name_str == "content-length": + corrected_name = "CONTENT_LENGTH" + elif name_str == "content-type": + corrected_name = "CONTENT_TYPE" + else: + corrected_name = "HTTP_%s" % name_str.upper().replace("-", "_") + # HTTPbis say only ASCII chars are allowed in headers, but we latin1 + # just in case + value_str: str = value.decode("latin1") + if corrected_name in environ: + corrected_name_environ = environ[corrected_name] + assert isinstance(corrected_name_environ, str) + value_str = corrected_name_environ + "," + value_str + environ[corrected_name] = value_str + return environ + + +class WSGIMiddleware: + def __init__(self, app: WSGIApp, workers: int = 10): + self.app = app + self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=workers) + + async def __call__( + self, + scope: "HTTPScope", + receive: "ASGIReceiveCallable", + send: "ASGISendCallable", + ) -> None: + assert scope["type"] == "http" + instance = WSGIResponder(self.app, self.executor, scope) + await instance(receive, send) + + +class WSGIResponder: + def __init__( + self, + app: WSGIApp, + executor: concurrent.futures.ThreadPoolExecutor, + scope: "HTTPScope", + ): + self.app = app + self.executor = executor + self.scope = scope + self.status = None + self.response_headers = None + self.send_event = asyncio.Event() + self.send_queue: Deque[Optional["ASGISendEvent"]] = deque() + self.loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() + self.response_started = False + self.exc_info: Optional[ExcInfo] = None + + async def __call__( + self, receive: "ASGIReceiveCallable", send: "ASGISendCallable" + ) -> None: + message: HTTPRequestEvent = await receive() # type: ignore[assignment] + body = io.BytesIO(message.get("body", b"")) + more_body = message.get("more_body", False) + if more_body: + body.seek(0, io.SEEK_END) + while more_body: + body_message: "HTTPRequestEvent" = ( + await receive() # type: ignore[assignment] + ) + body.write(body_message.get("body", b"")) + more_body = body_message.get("more_body", False) + body.seek(0) + environ = build_environ(self.scope, message, body) + self.loop = asyncio.get_event_loop() + wsgi = self.loop.run_in_executor( + self.executor, self.wsgi, environ, self.start_response + ) + sender = self.loop.create_task(self.sender(send)) + try: + await asyncio.wait_for(wsgi, None) + finally: + self.send_queue.append(None) + self.send_event.set() + await asyncio.wait_for(sender, None) + if self.exc_info is not None: + raise self.exc_info[0].with_traceback(self.exc_info[1], self.exc_info[2]) + + async def sender(self, send: "ASGISendCallable") -> None: + while True: + if self.send_queue: + message = self.send_queue.popleft() + if message is None: + return + await send(message) + else: + await self.send_event.wait() + self.send_event.clear() + + def start_response( + self, + status: str, + response_headers: Iterable[Tuple[str, str]], + exc_info: Optional[ExcInfo] = None, + ) -> None: + self.exc_info = exc_info + if not self.response_started: + self.response_started = True + status_code_str, _ = status.split(" ", 1) + status_code = int(status_code_str) + headers = [ + (name.encode("ascii"), value.encode("ascii")) + for name, value in response_headers + ] + http_response_start_event: HTTPResponseStartEvent = { + "type": "http.response.start", + "status": status_code, + "headers": headers, + } + self.send_queue.append(http_response_start_event) + self.loop.call_soon_threadsafe(self.send_event.set) + + def wsgi(self, environ: Environ, start_response: StartResponse) -> None: + for chunk in self.app(environ, start_response): # type: ignore + response_body: HTTPResponseBodyEvent = { + "type": "http.response.body", + "body": chunk, + "more_body": True, + } + self.send_queue.append(response_body) + self.loop.call_soon_threadsafe(self.send_event.set) + + empty_body: HTTPResponseBodyEvent = { + "type": "http.response.body", + "body": b"", + "more_body": False, + } + self.send_queue.append(empty_body) + self.loop.call_soon_threadsafe(self.send_event.set) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/auto.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/auto.py new file mode 100644 index 00000000..1aa99674 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/auto.py @@ -0,0 +1,14 @@ +import asyncio +from typing import Type + +AutoHTTPProtocol: Type[asyncio.Protocol] +try: + import httptools # noqa +except ImportError: # pragma: no cover + from uvicorn.protocols.http.h11_impl import H11Protocol + + AutoHTTPProtocol = H11Protocol +else: # pragma: no cover + from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol + + AutoHTTPProtocol = HttpToolsProtocol diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/flow_control.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/flow_control.py new file mode 100644 index 00000000..452c55f4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/flow_control.py @@ -0,0 +1,68 @@ +import asyncio +import typing + +if typing.TYPE_CHECKING: + from asgiref.typing import ( + ASGIReceiveCallable, + ASGISendCallable, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + Scope, + ) + +CLOSE_HEADER = (b"connection", b"close") + +HIGH_WATER_LIMIT = 65536 + + +class FlowControl: + def __init__(self, transport: asyncio.Transport) -> None: + self._transport = transport + self.read_paused = False + self.write_paused = False + self._is_writable_event = asyncio.Event() + self._is_writable_event.set() + + async def drain(self) -> None: + await self._is_writable_event.wait() + + def pause_reading(self) -> None: + if not self.read_paused: + self.read_paused = True + self._transport.pause_reading() + + def resume_reading(self) -> None: + if self.read_paused: + self.read_paused = False + self._transport.resume_reading() + + def pause_writing(self) -> None: + if not self.write_paused: + self.write_paused = True + self._is_writable_event.clear() + + def resume_writing(self) -> None: + if self.write_paused: + self.write_paused = False + self._is_writable_event.set() + + +async def service_unavailable( + scope: "Scope", receive: "ASGIReceiveCallable", send: "ASGISendCallable" +) -> None: + response_start: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": 503, + "headers": [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ], + } + await send(response_start) + + response_body: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": b"Service Unavailable", + "more_body": False, + } + await send(response_body) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/h11_impl.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/h11_impl.py new file mode 100644 index 00000000..5fff70bb --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/h11_impl.py @@ -0,0 +1,557 @@ +import asyncio +import http +import logging +import sys +from typing import TYPE_CHECKING, Callable, List, Optional, Tuple, Union, cast +from urllib.parse import unquote + +import h11 + +from uvicorn.config import Config +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.http.flow_control import ( + CLOSE_HEADER, + HIGH_WATER_LIMIT, + FlowControl, + service_unavailable, +) +from uvicorn.protocols.utils import ( + get_client_addr, + get_local_addr, + get_path_with_query_string, + get_remote_addr, + is_ssl, +) +from uvicorn.server import ServerState + +if sys.version_info < (3, 8): # pragma: py-gte-38 + from typing_extensions import Literal +else: # pragma: py-lt-38 + from typing import Literal + +if TYPE_CHECKING: + from asgiref.typing import ( + ASGI3Application, + ASGIReceiveEvent, + ASGISendEvent, + HTTPDisconnectEvent, + HTTPRequestEvent, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + HTTPScope, + ) + +H11Event = Union[ + h11.Request, + h11.InformationalResponse, + h11.Response, + h11.Data, + h11.EndOfMessage, + h11.ConnectionClosed, +] + + +def _get_status_phrase(status_code: int) -> bytes: + try: + return http.HTTPStatus(status_code).phrase.encode() + except ValueError: + return b"" + + +STATUS_PHRASES = { + status_code: _get_status_phrase(status_code) for status_code in range(100, 600) +} + + +class H11Protocol(asyncio.Protocol): + def __init__( + self, + config: Config, + server_state: ServerState, + _loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> None: + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.logger = logging.getLogger("uvicorn.error") + self.access_logger = logging.getLogger("uvicorn.access") + self.access_log = self.access_logger.hasHandlers() + self.conn = h11.Connection(h11.SERVER, config.h11_max_incomplete_event_size) + self.ws_protocol_class = config.ws_protocol_class + self.root_path = config.root_path + self.limit_concurrency = config.limit_concurrency + + # Timeouts + self.timeout_keep_alive_task: Optional[asyncio.TimerHandle] = None + self.timeout_keep_alive = config.timeout_keep_alive + + # Shared server state + self.server_state = server_state + self.connections = server_state.connections + self.tasks = server_state.tasks + self.default_headers = server_state.default_headers + + # Per-connection state + self.transport: asyncio.Transport = None # type: ignore[assignment] + self.flow: FlowControl = None # type: ignore[assignment] + self.server: Optional[Tuple[str, int]] = None + self.client: Optional[Tuple[str, int]] = None + self.scheme: Optional[Literal["http", "https"]] = None + + # Per-request state + self.scope: HTTPScope = None # type: ignore[assignment] + self.headers: List[Tuple[bytes, bytes]] = None # type: ignore[assignment] + self.cycle: RequestResponseCycle = None # type: ignore[assignment] + + # Protocol interface + def connection_made( # type: ignore[override] + self, transport: asyncio.Transport + ) -> None: + self.connections.add(self) + + self.transport = transport + self.flow = FlowControl(transport) + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "https" if is_ssl(transport) else "http" + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection made", prefix) + + def connection_lost(self, exc: Optional[Exception]) -> None: + self.connections.discard(self) + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection lost", prefix) + + if self.cycle and not self.cycle.response_complete: + self.cycle.disconnected = True + if self.conn.our_state != h11.ERROR: + event = h11.ConnectionClosed() + try: + self.conn.send(event) + except h11.LocalProtocolError: + # Premature client disconnect + pass + + if self.cycle is not None: + self.cycle.message_event.set() + if self.flow is not None: + self.flow.resume_writing() + if exc is None: + self.transport.close() + self._unset_keepalive_if_required() + + def eof_received(self) -> None: + pass + + def _unset_keepalive_if_required(self) -> None: + if self.timeout_keep_alive_task is not None: + self.timeout_keep_alive_task.cancel() + self.timeout_keep_alive_task = None + + def data_received(self, data: bytes) -> None: + self._unset_keepalive_if_required() + + self.conn.receive_data(data) + self.handle_events() + + def handle_events(self) -> None: + while True: + try: + event = self.conn.next_event() + except h11.RemoteProtocolError: + msg = "Invalid HTTP request received." + self.logger.warning(msg) + self.send_400_response(msg) + return + event_type = type(event) + + if event_type is h11.NEED_DATA: + break + + elif event_type is h11.PAUSED: + # This case can occur in HTTP pipelining, so we need to + # stop reading any more data, and ensure that at the end + # of the active request/response cycle we handle any + # events that have been buffered up. + self.flow.pause_reading() + break + + elif event_type is h11.Request: + self.headers = [(key.lower(), value) for key, value in event.headers] + raw_path, _, query_string = event.target.partition(b"?") + self.scope = { # type: ignore[typeddict-item] + "type": "http", + "asgi": { + "version": self.config.asgi_version, + "spec_version": "2.3", + }, + "http_version": event.http_version.decode("ascii"), + "server": self.server, + "client": self.client, + "scheme": self.scheme, + "method": event.method.decode("ascii"), + "root_path": self.root_path, + "path": unquote(raw_path.decode("ascii")), + "raw_path": raw_path, + "query_string": query_string, + "headers": self.headers, + } + + for name, value in self.headers: + if name == b"connection": + tokens = [token.lower().strip() for token in value.split(b",")] + if b"upgrade" in tokens: + self.handle_upgrade(event) + return + + # Handle 503 responses when 'limit_concurrency' is exceeded. + if self.limit_concurrency is not None and ( + len(self.connections) >= self.limit_concurrency + or len(self.tasks) >= self.limit_concurrency + ): + app = service_unavailable + message = "Exceeded concurrency limit." + self.logger.warning(message) + else: + app = self.app + + self.cycle = RequestResponseCycle( + scope=self.scope, + conn=self.conn, + transport=self.transport, + flow=self.flow, + logger=self.logger, + access_logger=self.access_logger, + access_log=self.access_log, + default_headers=self.default_headers, + message_event=asyncio.Event(), + on_response=self.on_response_complete, + ) + task = self.loop.create_task(self.cycle.run_asgi(app)) + task.add_done_callback(self.tasks.discard) + self.tasks.add(task) + + elif event_type is h11.Data: + if self.conn.our_state is h11.DONE: + continue + self.cycle.body += event.data + if len(self.cycle.body) > HIGH_WATER_LIMIT: + self.flow.pause_reading() + self.cycle.message_event.set() + + elif event_type is h11.EndOfMessage: + if self.conn.our_state is h11.DONE: + self.transport.resume_reading() + self.conn.start_next_cycle() + continue + self.cycle.more_body = False + self.cycle.message_event.set() + + def handle_upgrade(self, event: H11Event) -> None: + upgrade_value = None + for name, value in self.headers: + if name == b"upgrade": + upgrade_value = value.lower() + + if upgrade_value != b"websocket" or self.ws_protocol_class is None: + msg = "Unsupported upgrade request." + self.logger.warning(msg) + from uvicorn.protocols.websockets.auto import AutoWebSocketsProtocol + + if AutoWebSocketsProtocol is None: # pragma: no cover + msg = "No supported WebSocket library detected. Please use 'pip install uvicorn[standard]', or install 'websockets' or 'wsproto' manually." # noqa: E501 + self.logger.warning(msg) + self.send_400_response(msg) + return + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sUpgrading to WebSocket", prefix) + + self.connections.discard(self) + output = [event.method, b" ", event.target, b" HTTP/1.1\r\n"] + for name, value in self.headers: + output += [name, b": ", value, b"\r\n"] + output.append(b"\r\n") + protocol = self.ws_protocol_class( # type: ignore[call-arg] + config=self.config, server_state=self.server_state + ) + protocol.connection_made(self.transport) + protocol.data_received(b"".join(output)) + self.transport.set_protocol(protocol) + + def send_400_response(self, msg: str) -> None: + + reason = STATUS_PHRASES[400] + headers = [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ] + event = h11.Response(status_code=400, headers=headers, reason=reason) + output = self.conn.send(event) + self.transport.write(output) + event = h11.Data(data=msg.encode("ascii")) + output = self.conn.send(event) + self.transport.write(output) + event = h11.EndOfMessage() + output = self.conn.send(event) + self.transport.write(output) + self.transport.close() + + def on_response_complete(self) -> None: + self.server_state.total_requests += 1 + + if self.transport.is_closing(): + return + + # Set a short Keep-Alive timeout. + self._unset_keepalive_if_required() + + self.timeout_keep_alive_task = self.loop.call_later( + self.timeout_keep_alive, self.timeout_keep_alive_handler + ) + + # Unpause data reads if needed. + self.flow.resume_reading() + + # Unblock any pipelined events. + if self.conn.our_state is h11.DONE and self.conn.their_state is h11.DONE: + self.conn.start_next_cycle() + self.handle_events() + + def shutdown(self) -> None: + """ + Called by the server to commence a graceful shutdown. + """ + if self.cycle is None or self.cycle.response_complete: + event = h11.ConnectionClosed() + self.conn.send(event) + self.transport.close() + else: + self.cycle.keep_alive = False + + def pause_writing(self) -> None: + """ + Called by the transport when the write buffer exceeds the high water mark. + """ + self.flow.pause_writing() + + def resume_writing(self) -> None: + """ + Called by the transport when the write buffer drops below the low water mark. + """ + self.flow.resume_writing() + + def timeout_keep_alive_handler(self) -> None: + """ + Called on a keep-alive connection if no new data is received after a short + delay. + """ + if not self.transport.is_closing(): + event = h11.ConnectionClosed() + self.conn.send(event) + self.transport.close() + + +class RequestResponseCycle: + def __init__( + self, + scope: "HTTPScope", + conn: h11.Connection, + transport: asyncio.Transport, + flow: FlowControl, + logger: logging.Logger, + access_logger: logging.Logger, + access_log: bool, + default_headers: List[Tuple[bytes, bytes]], + message_event: asyncio.Event, + on_response: Callable[..., None], + ) -> None: + self.scope = scope + self.conn = conn + self.transport = transport + self.flow = flow + self.logger = logger + self.access_logger = access_logger + self.access_log = access_log + self.default_headers = default_headers + self.message_event = message_event + self.on_response = on_response + + # Connection state + self.disconnected = False + self.keep_alive = True + self.waiting_for_100_continue = conn.they_are_waiting_for_100_continue + + # Request state + self.body = b"" + self.more_body = True + + # Response state + self.response_started = False + self.response_complete = False + + # ASGI exception wrapper + async def run_asgi(self, app: "ASGI3Application") -> None: + try: + result = await app( # type: ignore[func-returns-value] + self.scope, self.receive, self.send + ) + except BaseException as exc: + msg = "Exception in ASGI application\n" + self.logger.error(msg, exc_info=exc) + if not self.response_started: + await self.send_500_response() + else: + self.transport.close() + else: + if result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + self.transport.close() + elif not self.response_started and not self.disconnected: + msg = "ASGI callable returned without starting response." + self.logger.error(msg) + await self.send_500_response() + elif not self.response_complete and not self.disconnected: + msg = "ASGI callable returned without completing response." + self.logger.error(msg) + self.transport.close() + finally: + self.on_response = lambda: None + + async def send_500_response(self) -> None: + response_start_event: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": 500, + "headers": [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ], + } + await self.send(response_start_event) + response_body_event: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": b"Internal Server Error", + "more_body": False, + } + await self.send(response_body_event) + + # ASGI interface + async def send(self, message: "ASGISendEvent") -> None: + message_type = message["type"] + + if self.flow.write_paused and not self.disconnected: + await self.flow.drain() + + if self.disconnected: + return + + if not self.response_started: + # Sending response status line and headers + if message_type != "http.response.start": + msg = "Expected ASGI message 'http.response.start', but got '%s'." + raise RuntimeError(msg % message_type) + message = cast("HTTPResponseStartEvent", message) + + self.response_started = True + self.waiting_for_100_continue = False + + status_code = message["status"] + message_headers = cast( + List[Tuple[bytes, bytes]], message.get("headers", []) + ) + headers = self.default_headers + message_headers + + if CLOSE_HEADER in self.scope["headers"] and CLOSE_HEADER not in headers: + headers = headers + [CLOSE_HEADER] + + if self.access_log: + self.access_logger.info( + '%s - "%s %s HTTP/%s" %d', + get_client_addr(self.scope), + self.scope["method"], + get_path_with_query_string(self.scope), + self.scope["http_version"], + status_code, + ) + + # Write response status line and headers + reason = STATUS_PHRASES[status_code] + event = h11.Response( + status_code=status_code, headers=headers, reason=reason + ) + output = self.conn.send(event) + self.transport.write(output) + + elif not self.response_complete: + # Sending response body + if message_type != "http.response.body": + msg = "Expected ASGI message 'http.response.body', but got '%s'." + raise RuntimeError(msg % message_type) + message = cast("HTTPResponseBodyEvent", message) + + body = message.get("body", b"") + more_body = message.get("more_body", False) + + # Write response body + if self.scope["method"] == "HEAD": + event = h11.Data(data=b"") + else: + event = h11.Data(data=body) + output = self.conn.send(event) + self.transport.write(output) + + # Handle response completion + if not more_body: + self.response_complete = True + self.message_event.set() + event = h11.EndOfMessage() + output = self.conn.send(event) + self.transport.write(output) + + else: + # Response already sent + msg = "Unexpected ASGI message '%s' sent, after response already completed." + raise RuntimeError(msg % message_type) + + if self.response_complete: + if self.conn.our_state is h11.MUST_CLOSE or not self.keep_alive: + event = h11.ConnectionClosed() + self.conn.send(event) + self.transport.close() + self.on_response() + + async def receive(self) -> "ASGIReceiveEvent": + if self.waiting_for_100_continue and not self.transport.is_closing(): + event = h11.InformationalResponse( + status_code=100, headers=[], reason="Continue" + ) + output = self.conn.send(event) + self.transport.write(output) + self.waiting_for_100_continue = False + + if not self.disconnected and not self.response_complete: + self.flow.resume_reading() + await self.message_event.wait() + self.message_event.clear() + + message: "Union[HTTPDisconnectEvent, HTTPRequestEvent]" + if self.disconnected or self.response_complete: + message = {"type": "http.disconnect"} + else: + message = { + "type": "http.request", + "body": self.body, + "more_body": self.more_body, + } + self.body = b"" + + return message diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/httptools_impl.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/httptools_impl.py new file mode 100644 index 00000000..f018c59a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/http/httptools_impl.py @@ -0,0 +1,579 @@ +import asyncio +import http +import logging +import re +import sys +import urllib +from asyncio.events import TimerHandle +from collections import deque +from typing import TYPE_CHECKING, Callable, Deque, List, Optional, Tuple, Union, cast + +import httptools + +from uvicorn.config import Config +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.http.flow_control import ( + CLOSE_HEADER, + HIGH_WATER_LIMIT, + FlowControl, + service_unavailable, +) +from uvicorn.protocols.utils import ( + get_client_addr, + get_local_addr, + get_path_with_query_string, + get_remote_addr, + is_ssl, +) +from uvicorn.server import ServerState + +if sys.version_info < (3, 8): # pragma: py-gte-38 + from typing_extensions import Literal +else: # pragma: py-lt-38 + from typing import Literal + +if TYPE_CHECKING: + from asgiref.typing import ( + ASGI3Application, + ASGIReceiveEvent, + ASGISendEvent, + HTTPDisconnectEvent, + HTTPRequestEvent, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + HTTPScope, + ) + +HEADER_RE = re.compile(b'[\x00-\x1F\x7F()<>@,;:[]={} \t\\"]') +HEADER_VALUE_RE = re.compile(b"[\x00-\x1F\x7F]") + + +def _get_status_line(status_code: int) -> bytes: + try: + phrase = http.HTTPStatus(status_code).phrase.encode() + except ValueError: + phrase = b"" + return b"".join([b"HTTP/1.1 ", str(status_code).encode(), b" ", phrase, b"\r\n"]) + + +STATUS_LINE = { + status_code: _get_status_line(status_code) for status_code in range(100, 600) +} + + +class HttpToolsProtocol(asyncio.Protocol): + def __init__( + self, + config: Config, + server_state: ServerState, + _loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> None: + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.logger = logging.getLogger("uvicorn.error") + self.access_logger = logging.getLogger("uvicorn.access") + self.access_log = self.access_logger.hasHandlers() + self.parser = httptools.HttpRequestParser(self) + self.ws_protocol_class = config.ws_protocol_class + self.root_path = config.root_path + self.limit_concurrency = config.limit_concurrency + + # Timeouts + self.timeout_keep_alive_task: Optional[TimerHandle] = None + self.timeout_keep_alive = config.timeout_keep_alive + + # Global state + self.server_state = server_state + self.connections = server_state.connections + self.tasks = server_state.tasks + self.default_headers = server_state.default_headers + + # Per-connection state + self.transport: asyncio.Transport = None # type: ignore[assignment] + self.flow: FlowControl = None # type: ignore[assignment] + self.server: Optional[Tuple[str, int]] = None + self.client: Optional[Tuple[str, int]] = None + self.scheme: Optional[Literal["http", "https"]] = None + self.pipeline: Deque[Tuple[RequestResponseCycle, ASGI3Application]] = deque() + + # Per-request state + self.scope: HTTPScope = None # type: ignore[assignment] + self.headers: List[Tuple[bytes, bytes]] = None # type: ignore[assignment] + self.expect_100_continue = False + self.cycle: RequestResponseCycle = None # type: ignore[assignment] + + # Protocol interface + def connection_made( # type: ignore[override] + self, transport: asyncio.Transport + ) -> None: + self.connections.add(self) + + self.transport = transport + self.flow = FlowControl(transport) + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "https" if is_ssl(transport) else "http" + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection made", prefix) + + def connection_lost(self, exc: Optional[Exception]) -> None: + self.connections.discard(self) + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection lost", prefix) + + if self.cycle and not self.cycle.response_complete: + self.cycle.disconnected = True + if self.cycle is not None: + self.cycle.message_event.set() + if self.flow is not None: + self.flow.resume_writing() + if exc is None: + self.transport.close() + self._unset_keepalive_if_required() + + self.parser = None + + def eof_received(self) -> None: + pass + + def _unset_keepalive_if_required(self) -> None: + if self.timeout_keep_alive_task is not None: + self.timeout_keep_alive_task.cancel() + self.timeout_keep_alive_task = None + + def data_received(self, data: bytes) -> None: + self._unset_keepalive_if_required() + + try: + self.parser.feed_data(data) + except httptools.HttpParserError: + msg = "Invalid HTTP request received." + self.logger.warning(msg) + self.send_400_response(msg) + return + except httptools.HttpParserUpgrade: + self.handle_upgrade() + + def handle_upgrade(self) -> None: + upgrade_value = None + for name, value in self.headers: + if name == b"upgrade": + upgrade_value = value.lower() + + if upgrade_value != b"websocket" or self.ws_protocol_class is None: + msg = "Unsupported upgrade request." + self.logger.warning(msg) + from uvicorn.protocols.websockets.auto import AutoWebSocketsProtocol + + if AutoWebSocketsProtocol is None: # pragma: no cover + msg = "No supported WebSocket library detected. Please use 'pip install uvicorn[standard]', or install 'websockets' or 'wsproto' manually." # noqa: E501 + self.logger.warning(msg) + self.send_400_response(msg) + return + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sUpgrading to WebSocket", prefix) + + self.connections.discard(self) + method = self.scope["method"].encode() + output = [method, b" ", self.url, b" HTTP/1.1\r\n"] + for name, value in self.scope["headers"]: + output += [name, b": ", value, b"\r\n"] + output.append(b"\r\n") + protocol = self.ws_protocol_class( # type: ignore[call-arg] + config=self.config, server_state=self.server_state + ) + protocol.connection_made(self.transport) + protocol.data_received(b"".join(output)) + self.transport.set_protocol(protocol) + + def send_400_response(self, msg: str) -> None: + + content = [STATUS_LINE[400]] + for name, value in self.default_headers: + content.extend([name, b": ", value, b"\r\n"]) + content.extend( + [ + b"content-type: text/plain; charset=utf-8\r\n", + b"content-length: " + str(len(msg)).encode("ascii") + b"\r\n", + b"connection: close\r\n", + b"\r\n", + msg.encode("ascii"), + ] + ) + self.transport.write(b"".join(content)) + self.transport.close() + + def on_message_begin(self) -> None: + self.url = b"" + self.expect_100_continue = False + self.headers = [] + self.scope = { # type: ignore[typeddict-item] + "type": "http", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"}, + "http_version": "1.1", + "server": self.server, + "client": self.client, + "scheme": self.scheme, + "root_path": self.root_path, + "headers": self.headers, + } + + # Parser callbacks + def on_url(self, url: bytes) -> None: + self.url += url + + def on_header(self, name: bytes, value: bytes) -> None: + name = name.lower() + if name == b"expect" and value.lower() == b"100-continue": + self.expect_100_continue = True + self.headers.append((name, value)) + + def on_headers_complete(self) -> None: + http_version = self.parser.get_http_version() + method = self.parser.get_method() + self.scope["method"] = method.decode("ascii") + if http_version != "1.1": + self.scope["http_version"] = http_version + if self.parser.should_upgrade(): + return + parsed_url = httptools.parse_url(self.url) + raw_path = parsed_url.path + path = raw_path.decode("ascii") + if "%" in path: + path = urllib.parse.unquote(path) + self.scope["path"] = path + self.scope["raw_path"] = raw_path + self.scope["query_string"] = parsed_url.query or b"" + + # Handle 503 responses when 'limit_concurrency' is exceeded. + if self.limit_concurrency is not None and ( + len(self.connections) >= self.limit_concurrency + or len(self.tasks) >= self.limit_concurrency + ): + app = service_unavailable + message = "Exceeded concurrency limit." + self.logger.warning(message) + else: + app = self.app + + existing_cycle = self.cycle + self.cycle = RequestResponseCycle( + scope=self.scope, + transport=self.transport, + flow=self.flow, + logger=self.logger, + access_logger=self.access_logger, + access_log=self.access_log, + default_headers=self.default_headers, + message_event=asyncio.Event(), + expect_100_continue=self.expect_100_continue, + keep_alive=http_version != "1.0", + on_response=self.on_response_complete, + ) + if existing_cycle is None or existing_cycle.response_complete: + # Standard case - start processing the request. + task = self.loop.create_task(self.cycle.run_asgi(app)) + task.add_done_callback(self.tasks.discard) + self.tasks.add(task) + else: + # Pipelined HTTP requests need to be queued up. + self.flow.pause_reading() + self.pipeline.appendleft((self.cycle, app)) + + def on_body(self, body: bytes) -> None: + if self.parser.should_upgrade() or self.cycle.response_complete: + return + self.cycle.body += body + if len(self.cycle.body) > HIGH_WATER_LIMIT: + self.flow.pause_reading() + self.cycle.message_event.set() + + def on_message_complete(self) -> None: + if self.parser.should_upgrade() or self.cycle.response_complete: + return + self.cycle.more_body = False + self.cycle.message_event.set() + + def on_response_complete(self) -> None: + # Callback for pipelined HTTP requests to be started. + self.server_state.total_requests += 1 + + if self.transport.is_closing(): + return + + # Set a short Keep-Alive timeout. + self._unset_keepalive_if_required() + + self.timeout_keep_alive_task = self.loop.call_later( + self.timeout_keep_alive, self.timeout_keep_alive_handler + ) + + # Unpause data reads if needed. + self.flow.resume_reading() + + # Unblock any pipelined events. + if self.pipeline: + cycle, app = self.pipeline.pop() + task = self.loop.create_task(cycle.run_asgi(app)) + task.add_done_callback(self.tasks.discard) + self.tasks.add(task) + + def shutdown(self) -> None: + """ + Called by the server to commence a graceful shutdown. + """ + if self.cycle is None or self.cycle.response_complete: + self.transport.close() + else: + self.cycle.keep_alive = False + + def pause_writing(self) -> None: + """ + Called by the transport when the write buffer exceeds the high water mark. + """ + self.flow.pause_writing() + + def resume_writing(self) -> None: + """ + Called by the transport when the write buffer drops below the low water mark. + """ + self.flow.resume_writing() + + def timeout_keep_alive_handler(self) -> None: + """ + Called on a keep-alive connection if no new data is received after a short + delay. + """ + if not self.transport.is_closing(): + self.transport.close() + + +class RequestResponseCycle: + def __init__( + self, + scope: "HTTPScope", + transport: asyncio.Transport, + flow: FlowControl, + logger: logging.Logger, + access_logger: logging.Logger, + access_log: bool, + default_headers: List[Tuple[bytes, bytes]], + message_event: asyncio.Event, + expect_100_continue: bool, + keep_alive: bool, + on_response: Callable[..., None], + ): + self.scope = scope + self.transport = transport + self.flow = flow + self.logger = logger + self.access_logger = access_logger + self.access_log = access_log + self.default_headers = default_headers + self.message_event = message_event + self.on_response = on_response + + # Connection state + self.disconnected = False + self.keep_alive = keep_alive + self.waiting_for_100_continue = expect_100_continue + + # Request state + self.body = b"" + self.more_body = True + + # Response state + self.response_started = False + self.response_complete = False + self.chunked_encoding: Optional[bool] = None + self.expected_content_length = 0 + + # ASGI exception wrapper + async def run_asgi(self, app: "ASGI3Application") -> None: + try: + result = await app( # type: ignore[func-returns-value] + self.scope, self.receive, self.send + ) + except BaseException as exc: + msg = "Exception in ASGI application\n" + self.logger.error(msg, exc_info=exc) + if not self.response_started: + await self.send_500_response() + else: + self.transport.close() + else: + if result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + self.transport.close() + elif not self.response_started and not self.disconnected: + msg = "ASGI callable returned without starting response." + self.logger.error(msg) + await self.send_500_response() + elif not self.response_complete and not self.disconnected: + msg = "ASGI callable returned without completing response." + self.logger.error(msg) + self.transport.close() + finally: + self.on_response = lambda: None + + async def send_500_response(self) -> None: + response_start_event: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": 500, + "headers": [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ], + } + await self.send(response_start_event) + response_body_event: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": b"Internal Server Error", + "more_body": False, + } + await self.send(response_body_event) + + # ASGI interface + async def send(self, message: "ASGISendEvent") -> None: + message_type = message["type"] + + if self.flow.write_paused and not self.disconnected: + await self.flow.drain() + + if self.disconnected: + return + + if not self.response_started: + # Sending response status line and headers + if message_type != "http.response.start": + msg = "Expected ASGI message 'http.response.start', but got '%s'." + raise RuntimeError(msg % message_type) + message = cast("HTTPResponseStartEvent", message) + + self.response_started = True + self.waiting_for_100_continue = False + + status_code = message["status"] + headers = self.default_headers + list(message.get("headers", [])) + + if CLOSE_HEADER in self.scope["headers"] and CLOSE_HEADER not in headers: + headers = headers + [CLOSE_HEADER] + + if self.access_log: + self.access_logger.info( + '%s - "%s %s HTTP/%s" %d', + get_client_addr(self.scope), + self.scope["method"], + get_path_with_query_string(self.scope), + self.scope["http_version"], + status_code, + ) + + # Write response status line and headers + content = [STATUS_LINE[status_code]] + + for name, value in headers: + if HEADER_RE.search(name): + raise RuntimeError("Invalid HTTP header name.") + if HEADER_VALUE_RE.search(value): + raise RuntimeError("Invalid HTTP header value.") + + name = name.lower() + if name == b"content-length" and self.chunked_encoding is None: + self.expected_content_length = int(value.decode()) + self.chunked_encoding = False + elif name == b"transfer-encoding" and value.lower() == b"chunked": + self.expected_content_length = 0 + self.chunked_encoding = True + elif name == b"connection" and value.lower() == b"close": + self.keep_alive = False + content.extend([name, b": ", value, b"\r\n"]) + + if ( + self.chunked_encoding is None + and self.scope["method"] != "HEAD" + and status_code not in (204, 304) + ): + # Neither content-length nor transfer-encoding specified + self.chunked_encoding = True + content.append(b"transfer-encoding: chunked\r\n") + + content.append(b"\r\n") + self.transport.write(b"".join(content)) + + elif not self.response_complete: + # Sending response body + if message_type != "http.response.body": + msg = "Expected ASGI message 'http.response.body', but got '%s'." + raise RuntimeError(msg % message_type) + + body = cast(bytes, message.get("body", b"")) + more_body = message.get("more_body", False) + + # Write response body + if self.scope["method"] == "HEAD": + self.expected_content_length = 0 + elif self.chunked_encoding: + if body: + content = [b"%x\r\n" % len(body), body, b"\r\n"] + else: + content = [] + if not more_body: + content.append(b"0\r\n\r\n") + self.transport.write(b"".join(content)) + else: + num_bytes = len(body) + if num_bytes > self.expected_content_length: + raise RuntimeError("Response content longer than Content-Length") + else: + self.expected_content_length -= num_bytes + self.transport.write(body) + + # Handle response completion + if not more_body: + if self.expected_content_length != 0: + raise RuntimeError("Response content shorter than Content-Length") + self.response_complete = True + self.message_event.set() + if not self.keep_alive: + self.transport.close() + self.on_response() + + else: + # Response already sent + msg = "Unexpected ASGI message '%s' sent, after response already completed." + raise RuntimeError(msg % message_type) + + async def receive(self) -> "ASGIReceiveEvent": + if self.waiting_for_100_continue and not self.transport.is_closing(): + self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n") + self.waiting_for_100_continue = False + + if not self.disconnected and not self.response_complete: + self.flow.resume_reading() + await self.message_event.wait() + self.message_event.clear() + + message: "Union[HTTPDisconnectEvent, HTTPRequestEvent]" + if self.disconnected or self.response_complete: + message = {"type": "http.disconnect"} + else: + message = { + "type": "http.request", + "body": self.body, + "more_body": self.more_body, + } + self.body = b"" + + return message diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/utils.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/utils.py new file mode 100644 index 00000000..fbd4b4d5 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/utils.py @@ -0,0 +1,55 @@ +import asyncio +import urllib.parse +from typing import TYPE_CHECKING, Optional, Tuple + +if TYPE_CHECKING: + from asgiref.typing import WWWScope + + +def get_remote_addr(transport: asyncio.Transport) -> Optional[Tuple[str, int]]: + socket_info = transport.get_extra_info("socket") + if socket_info is not None: + try: + info = socket_info.getpeername() + return (str(info[0]), int(info[1])) if isinstance(info, tuple) else None + except OSError: # pragma: no cover + # This case appears to inconsistently occur with uvloop + # bound to a unix domain socket. + return None + + info = transport.get_extra_info("peername") + if info is not None and isinstance(info, (list, tuple)) and len(info) == 2: + return (str(info[0]), int(info[1])) + return None + + +def get_local_addr(transport: asyncio.Transport) -> Optional[Tuple[str, int]]: + socket_info = transport.get_extra_info("socket") + if socket_info is not None: + info = socket_info.getsockname() + + return (str(info[0]), int(info[1])) if isinstance(info, tuple) else None + info = transport.get_extra_info("sockname") + if info is not None and isinstance(info, (list, tuple)) and len(info) == 2: + return (str(info[0]), int(info[1])) + return None + + +def is_ssl(transport: asyncio.Transport) -> bool: + return bool(transport.get_extra_info("sslcontext")) + + +def get_client_addr(scope: "WWWScope") -> str: + client = scope.get("client") + if not client: + return "" + return "%s:%d" % client + + +def get_path_with_query_string(scope: "WWWScope") -> str: + path_with_query_string = urllib.parse.quote(scope["path"]) + if scope["query_string"]: + path_with_query_string = "{}?{}".format( + path_with_query_string, scope["query_string"].decode("ascii") + ) + return path_with_query_string diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/auto.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/auto.py new file mode 100644 index 00000000..0dfba3bd --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/auto.py @@ -0,0 +1,19 @@ +import asyncio +import typing + +AutoWebSocketsProtocol: typing.Optional[typing.Type[asyncio.Protocol]] +try: + import websockets # noqa +except ImportError: # pragma: no cover + try: + import wsproto # noqa + except ImportError: + AutoWebSocketsProtocol = None + else: + from uvicorn.protocols.websockets.wsproto_impl import WSProtocol + + AutoWebSocketsProtocol = WSProtocol +else: + from uvicorn.protocols.websockets.websockets_impl import WebSocketProtocol + + AutoWebSocketsProtocol = WebSocketProtocol diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/websockets_impl.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/websockets_impl.py new file mode 100644 index 00000000..eea7a65b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/websockets_impl.py @@ -0,0 +1,350 @@ +import asyncio +import http +import logging +import sys +from typing import TYPE_CHECKING, Any, List, Optional, Sequence, Tuple, Union, cast +from urllib.parse import unquote + +import websockets +from websockets.datastructures import Headers +from websockets.exceptions import ConnectionClosed +from websockets.extensions.permessage_deflate import ServerPerMessageDeflateFactory +from websockets.legacy.server import HTTPResponse +from websockets.server import WebSocketServerProtocol +from websockets.typing import Subprotocol + +from uvicorn.config import Config +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.utils import get_local_addr, get_remote_addr, is_ssl +from uvicorn.server import ServerState + +if sys.version_info < (3, 8): + from typing_extensions import Literal +else: + from typing import Literal + +if TYPE_CHECKING: + from asgiref.typing import ( + ASGISendEvent, + WebSocketAcceptEvent, + WebSocketCloseEvent, + WebSocketConnectEvent, + WebSocketDisconnectEvent, + WebSocketReceiveEvent, + WebSocketScope, + WebSocketSendEvent, + ) + + +class Server: + closing = False + + def register(self, ws: WebSocketServerProtocol) -> None: + pass + + def unregister(self, ws: WebSocketServerProtocol) -> None: + pass + + def is_serving(self) -> bool: + return not self.closing + + +class WebSocketProtocol(WebSocketServerProtocol): + extra_headers: List[Tuple[str, str]] + + def __init__( + self, + config: Config, + server_state: ServerState, + _loop: Optional[asyncio.AbstractEventLoop] = None, + ): + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.root_path = config.root_path + + # Shared server state + self.connections = server_state.connections + self.tasks = server_state.tasks + + # Connection state + self.transport: asyncio.Transport = None # type: ignore[assignment] + self.server: Optional[Tuple[str, int]] = None + self.client: Optional[Tuple[str, int]] = None + self.scheme: Literal["wss", "ws"] = None # type: ignore[assignment] + + # Connection events + self.scope: WebSocketScope = None # type: ignore[assignment] + self.handshake_started_event = asyncio.Event() + self.handshake_completed_event = asyncio.Event() + self.closed_event = asyncio.Event() + self.initial_response: Optional[HTTPResponse] = None + self.connect_sent = False + self.accepted_subprotocol: Optional[Subprotocol] = None + self.transfer_data_task: asyncio.Task = None # type: ignore[assignment] + + self.ws_server: Server = Server() # type: ignore[assignment] + + extensions = [] + if self.config.ws_per_message_deflate: + extensions.append(ServerPerMessageDeflateFactory()) + + super().__init__( + ws_handler=self.ws_handler, + ws_server=self.ws_server, # type: ignore[arg-type] + max_size=self.config.ws_max_size, + ping_interval=self.config.ws_ping_interval, + ping_timeout=self.config.ws_ping_timeout, + extensions=extensions, + logger=logging.getLogger("uvicorn.error"), + extra_headers=[], + ) + + def connection_made( # type: ignore[override] + self, transport: asyncio.Transport + ) -> None: + self.connections.add(self) + self.transport = transport + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "wss" if is_ssl(transport) else "ws" + + if self.logger.isEnabledFor(TRACE_LOG_LEVEL): + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection made", prefix) + + super().connection_made(transport) + + def connection_lost(self, exc: Optional[Exception]) -> None: + self.connections.remove(self) + + if self.logger.isEnabledFor(TRACE_LOG_LEVEL): + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection lost", prefix) + + self.handshake_completed_event.set() + super().connection_lost(exc) + if exc is None: + self.transport.close() + + def shutdown(self) -> None: + self.ws_server.closing = True + self.transport.close() + + def on_task_complete(self, task: asyncio.Task) -> None: + self.tasks.discard(task) + + async def process_request( + self, path: str, headers: Headers + ) -> Optional[HTTPResponse]: + """ + This hook is called to determine if the websocket should return + an HTTP response and close. + + Our behavior here is to start the ASGI application, and then wait + for either `accept` or `close` in order to determine if we should + close the connection. + """ + path_portion, _, query_string = path.partition("?") + + websockets.legacy.handshake.check_request(headers) + + subprotocols = [] + for header in headers.get_all("Sec-WebSocket-Protocol"): + subprotocols.extend([token.strip() for token in header.split(",")]) + + asgi_headers = [ + (name.encode("ascii"), value.encode("ascii")) + for name, value in headers.raw_items() + ] + + self.scope = { # type: ignore[typeddict-item] + "type": "websocket", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"}, + "http_version": "1.1", + "scheme": self.scheme, + "server": self.server, + "client": self.client, + "root_path": self.root_path, + "path": unquote(path_portion), + "raw_path": path_portion.encode("ascii"), + "query_string": query_string.encode("ascii"), + "headers": asgi_headers, + "subprotocols": subprotocols, + } + task = self.loop.create_task(self.run_asgi()) + task.add_done_callback(self.on_task_complete) + self.tasks.add(task) + await self.handshake_started_event.wait() + return self.initial_response + + def process_subprotocol( + self, headers: Headers, available_subprotocols: Optional[Sequence[Subprotocol]] + ) -> Optional[Subprotocol]: + """ + We override the standard 'process_subprotocol' behavior here so that + we return whatever subprotocol is sent in the 'accept' message. + """ + return self.accepted_subprotocol + + def send_500_response(self) -> None: + msg = b"Internal Server Error" + content = [ + b"HTTP/1.1 500 Internal Server Error\r\n" + b"content-type: text/plain; charset=utf-8\r\n", + b"content-length: " + str(len(msg)).encode("ascii") + b"\r\n", + b"connection: close\r\n", + b"\r\n", + msg, + ] + self.transport.write(b"".join(content)) + # Allow handler task to terminate cleanly, as websockets doesn't cancel it by + # itself (see https://github.com/encode/uvicorn/issues/920) + self.handshake_started_event.set() + + async def ws_handler( # type: ignore[override] + self, protocol: WebSocketServerProtocol, path: str + ) -> Any: + """ + This is the main handler function for the 'websockets' implementation + to call into. We just wait for close then return, and instead allow + 'send' and 'receive' events to drive the flow. + """ + self.handshake_completed_event.set() + await self.closed_event.wait() + + async def run_asgi(self) -> None: + """ + Wrapper around the ASGI callable, handling exceptions and unexpected + termination states. + """ + try: + result = await self.app(self.scope, self.asgi_receive, self.asgi_send) + except BaseException as exc: + self.closed_event.set() + msg = "Exception in ASGI application\n" + self.logger.error(msg, exc_info=exc) + if not self.handshake_started_event.is_set(): + self.send_500_response() + else: + await self.handshake_completed_event.wait() + self.transport.close() + else: + self.closed_event.set() + if not self.handshake_started_event.is_set(): + msg = "ASGI callable returned without sending handshake." + self.logger.error(msg) + self.send_500_response() + self.transport.close() + elif result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + await self.handshake_completed_event.wait() + self.transport.close() + + async def asgi_send(self, message: "ASGISendEvent") -> None: + message_type = message["type"] + + if not self.handshake_started_event.is_set(): + if message_type == "websocket.accept": + message = cast("WebSocketAcceptEvent", message) + self.logger.info( + '%s - "WebSocket %s" [accepted]', + self.scope["client"], + self.scope["path"], + ) + self.initial_response = None + self.accepted_subprotocol = cast( + Optional[Subprotocol], message.get("subprotocol") + ) + if "headers" in message: + self.extra_headers.extend( + # ASGI spec requires bytes + # But for compatibility we need to convert it to strings + (name.decode("latin-1"), value.decode("latin-1")) + for name, value in message["headers"] + ) + self.handshake_started_event.set() + + elif message_type == "websocket.close": + message = cast("WebSocketCloseEvent", message) + self.logger.info( + '%s - "WebSocket %s" 403', + self.scope["client"], + self.scope["path"], + ) + self.initial_response = (http.HTTPStatus.FORBIDDEN, [], b"") + self.handshake_started_event.set() + self.closed_event.set() + + else: + msg = ( + "Expected ASGI message 'websocket.accept' or 'websocket.close', " + "but got '%s'." + ) + raise RuntimeError(msg % message_type) + + elif not self.closed_event.is_set(): + await self.handshake_completed_event.wait() + + if message_type == "websocket.send": + message = cast("WebSocketSendEvent", message) + bytes_data = message.get("bytes") + text_data = message.get("text") + data = text_data if bytes_data is None else bytes_data + await self.send(data) # type: ignore[arg-type] + + elif message_type == "websocket.close": + message = cast("WebSocketCloseEvent", message) + code = message.get("code", 1000) + reason = message.get("reason", "") or "" + await self.close(code, reason) + self.closed_event.set() + + else: + msg = ( + "Expected ASGI message 'websocket.send' or 'websocket.close'," + " but got '%s'." + ) + raise RuntimeError(msg % message_type) + + else: + msg = "Unexpected ASGI message '%s', after sending 'websocket.close'." + raise RuntimeError(msg % message_type) + + async def asgi_receive( + self, + ) -> Union[ + "WebSocketDisconnectEvent", "WebSocketConnectEvent", "WebSocketReceiveEvent" + ]: + if not self.connect_sent: + self.connect_sent = True + return {"type": "websocket.connect"} + + await self.handshake_completed_event.wait() + + if self.closed_event.is_set(): + # If client disconnected, use WebSocketServerProtocol.close_code property. + # If the handshake failed or the app closed before handshake completion, + # use 1006 Abnormal Closure. + return {"type": "websocket.disconnect", "code": self.close_code or 1006} + + try: + data = await self.recv() + except ConnectionClosed as exc: + self.closed_event.set() + return {"type": "websocket.disconnect", "code": exc.code} + + msg: WebSocketReceiveEvent = { # type: ignore[typeddict-item] + "type": "websocket.receive" + } + + if isinstance(data, str): + msg["text"] = data + else: + msg["bytes"] = data + + return msg diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/wsproto_impl.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/wsproto_impl.py new file mode 100644 index 00000000..eb8d860b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/protocols/websockets/wsproto_impl.py @@ -0,0 +1,322 @@ +import asyncio +import logging +from urllib.parse import unquote + +import h11 +import wsproto +from wsproto import ConnectionType, events +from wsproto.connection import ConnectionState +from wsproto.extensions import PerMessageDeflate +from wsproto.utilities import RemoteProtocolError + +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.utils import get_local_addr, get_remote_addr, is_ssl + + +class WSProtocol(asyncio.Protocol): + def __init__(self, config, server_state, _loop=None): + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.logger = logging.getLogger("uvicorn.error") + self.root_path = config.root_path + + # Shared server state + self.connections = server_state.connections + self.tasks = server_state.tasks + + # Connection state + self.transport = None + self.server = None + self.client = None + self.scheme = None + + # WebSocket state + self.connect_event = None + self.queue = asyncio.Queue() + self.handshake_complete = False + self.close_sent = False + + self.conn = wsproto.WSConnection(connection_type=ConnectionType.SERVER) + + self.read_paused = False + self.writable = asyncio.Event() + self.writable.set() + + # Buffers + self.bytes = b"" + self.text = "" + + # Protocol interface + + def connection_made(self, transport): + self.connections.add(self) + self.transport = transport + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "wss" if is_ssl(transport) else "ws" + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % tuple(self.client) if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection made", prefix) + + def connection_lost(self, exc): + if exc is not None: + self.queue.put_nowait({"type": "websocket.disconnect"}) + self.connections.remove(self) + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % tuple(self.client) if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection lost", prefix) + + if exc is None: + self.transport.close() + + def eof_received(self): + pass + + def data_received(self, data): + try: + self.conn.receive_data(data) + except RemoteProtocolError as err: + if err.event_hint is not None: + self.transport.write(self.conn.send(err.event_hint)) + self.transport.close() + else: + self.handle_no_connect(events.CloseConnection()) + else: + self.handle_events() + + def handle_events(self): + for event in self.conn.events(): + if isinstance(event, events.Request): + self.handle_connect(event) + elif isinstance(event, events.TextMessage): + self.handle_text(event) + elif isinstance(event, events.BytesMessage): + self.handle_bytes(event) + elif isinstance(event, events.RejectConnection): + self.handle_no_connect(event) + elif isinstance(event, events.RejectData): + self.handle_no_connect(event) + elif isinstance(event, events.CloseConnection): + self.handle_close(event) + elif isinstance(event, events.Ping): + self.handle_ping(event) + + def pause_writing(self): + """ + Called by the transport when the write buffer exceeds the high water mark. + """ + self.writable.clear() + + def resume_writing(self): + """ + Called by the transport when the write buffer drops below the low water mark. + """ + self.writable.set() + + def shutdown(self): + self.queue.put_nowait({"type": "websocket.disconnect", "code": 1012}) + output = self.conn.send(wsproto.events.CloseConnection(code=1012)) + self.transport.write(output) + self.transport.close() + + def on_task_complete(self, task): + self.tasks.discard(task) + + # Event handlers + + def handle_connect(self, event): + self.connect_event = event + headers = [(b"host", event.host.encode())] + headers += [(key.lower(), value) for key, value in event.extra_headers] + raw_path, _, query_string = event.target.partition("?") + self.scope = { + "type": "websocket", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"}, + "http_version": "1.1", + "scheme": self.scheme, + "server": self.server, + "client": self.client, + "root_path": self.root_path, + "path": unquote(raw_path), + "raw_path": raw_path.encode("ascii"), + "query_string": query_string.encode("ascii"), + "headers": headers, + "subprotocols": event.subprotocols, + } + self.queue.put_nowait({"type": "websocket.connect"}) + task = self.loop.create_task(self.run_asgi()) + task.add_done_callback(self.on_task_complete) + self.tasks.add(task) + + def handle_no_connect(self, event): + headers = [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ] + msg = h11.Response(status_code=400, headers=headers, reason="Bad Request") + output = self.conn.send(msg) + msg = h11.Data(data=event.reason.encode("utf-8")) + output += self.conn.send(msg) + msg = h11.EndOfMessage() + output += self.conn.send(msg) + self.transport.write(output) + self.transport.close() + + def handle_text(self, event): + self.text += event.data + if event.message_finished: + self.queue.put_nowait({"type": "websocket.receive", "text": self.text}) + self.text = "" + if not self.read_paused: + self.read_paused = True + self.transport.pause_reading() + + def handle_bytes(self, event): + self.bytes += event.data + # todo: we may want to guard the size of self.bytes and self.text + if event.message_finished: + self.queue.put_nowait({"type": "websocket.receive", "bytes": self.bytes}) + self.bytes = b"" + if not self.read_paused: + self.read_paused = True + self.transport.pause_reading() + + def handle_close(self, event): + if self.conn.state == ConnectionState.REMOTE_CLOSING: + self.transport.write(self.conn.send(event.response())) + self.queue.put_nowait({"type": "websocket.disconnect", "code": event.code}) + self.transport.close() + + def handle_ping(self, event): + self.transport.write(self.conn.send(event.response())) + + def send_500_response(self): + headers = [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ] + if self.conn.connection is None: + output = self.conn.send(wsproto.events.RejectConnection(status_code=500)) + else: + msg = h11.Response( + status_code=500, headers=headers, reason="Internal Server Error" + ) + output = self.conn.send(msg) + msg = h11.Data(data=b"Internal Server Error") + output += self.conn.send(msg) + msg = h11.EndOfMessage() + output += self.conn.send(msg) + self.transport.write(output) + + async def run_asgi(self): + try: + result = await self.app(self.scope, self.receive, self.send) + except BaseException as exc: + msg = "Exception in ASGI application\n" + self.logger.error(msg, exc_info=exc) + if not self.handshake_complete: + self.send_500_response() + self.transport.close() + else: + if not self.handshake_complete: + msg = "ASGI callable returned without completing handshake." + self.logger.error(msg) + self.send_500_response() + self.transport.close() + elif result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + self.transport.close() + + async def send(self, message): + await self.writable.wait() + + message_type = message["type"] + + if not self.handshake_complete: + if message_type == "websocket.accept": + self.logger.info( + '%s - "WebSocket %s" [accepted]', + self.scope["client"], + self.scope["path"], + ) + self.handshake_complete = True + subprotocol = message.get("subprotocol") + extra_headers = message.get("headers", []) + extensions = [] + if self.config.ws_per_message_deflate: + extensions.append(PerMessageDeflate()) + output = self.conn.send( + wsproto.events.AcceptConnection( + subprotocol=subprotocol, + extensions=extensions, + extra_headers=extra_headers, + ) + ) + self.transport.write(output) + + elif message_type == "websocket.close": + self.queue.put_nowait({"type": "websocket.disconnect", "code": None}) + self.logger.info( + '%s - "WebSocket %s" 403', + self.scope["client"], + self.scope["path"], + ) + self.handshake_complete = True + self.close_sent = True + msg = events.RejectConnection(status_code=403, headers=[]) + output = self.conn.send(msg) + self.transport.write(output) + self.transport.close() + + else: + msg = ( + "Expected ASGI message 'websocket.accept' or 'websocket.close', " + "but got '%s'." + ) + raise RuntimeError(msg % message_type) + + elif not self.close_sent: + if message_type == "websocket.send": + bytes_data = message.get("bytes") + text_data = message.get("text") + data = text_data if bytes_data is None else bytes_data + output = self.conn.send(wsproto.events.Message(data=data)) + if not self.transport.is_closing(): + self.transport.write(output) + + elif message_type == "websocket.close": + self.close_sent = True + code = message.get("code", 1000) + reason = message.get("reason", "") or "" + self.queue.put_nowait({"type": "websocket.disconnect", "code": code}) + output = self.conn.send( + wsproto.events.CloseConnection(code=code, reason=reason) + ) + if not self.transport.is_closing(): + self.transport.write(output) + self.transport.close() + + else: + msg = ( + "Expected ASGI message 'websocket.send' or 'websocket.close'," + " but got '%s'." + ) + raise RuntimeError(msg % message_type) + + else: + msg = "Unexpected ASGI message '%s', after sending 'websocket.close'." + raise RuntimeError(msg % message_type) + + async def receive(self): + message = await self.queue.get() + if self.read_paused and self.queue.empty(): + self.read_paused = False + self.transport.resume_reading() + return message diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/server.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/server.py new file mode 100644 index 00000000..494e2b65 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/server.py @@ -0,0 +1,306 @@ +import asyncio +import functools +import logging +import os +import platform +import signal +import socket +import sys +import threading +import time +from email.utils import formatdate +from types import FrameType +from typing import TYPE_CHECKING, List, Optional, Sequence, Set, Tuple, Union + +import click + +from uvicorn.config import Config + +if TYPE_CHECKING: + from uvicorn.protocols.http.h11_impl import H11Protocol + from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol + from uvicorn.protocols.websockets.websockets_impl import WebSocketProtocol + from uvicorn.protocols.websockets.wsproto_impl import WSProtocol + + Protocols = Union[H11Protocol, HttpToolsProtocol, WSProtocol, WebSocketProtocol] + + +HANDLED_SIGNALS = ( + signal.SIGINT, # Unix signal 2. Sent by Ctrl+C. + signal.SIGTERM, # Unix signal 15. Sent by `kill `. +) + +logger = logging.getLogger("uvicorn.error") + + +class ServerState: + """ + Shared servers state that is available between all protocol instances. + """ + + def __init__(self) -> None: + self.total_requests = 0 + self.connections: Set["Protocols"] = set() + self.tasks: Set[asyncio.Task] = set() + self.default_headers: List[Tuple[bytes, bytes]] = [] + + +class Server: + def __init__(self, config: Config) -> None: + self.config = config + self.server_state = ServerState() + + self.started = False + self.should_exit = False + self.force_exit = False + self.last_notified = 0.0 + + def run(self, sockets: Optional[List[socket.socket]] = None) -> None: + self.config.setup_event_loop() + return asyncio.run(self.serve(sockets=sockets)) + + async def serve(self, sockets: Optional[List[socket.socket]] = None) -> None: + process_id = os.getpid() + + config = self.config + if not config.loaded: + config.load() + + self.lifespan = config.lifespan_class(config) + + self.install_signal_handlers() + + message = "Started server process [%d]" + color_message = "Started server process [" + click.style("%d", fg="cyan") + "]" + logger.info(message, process_id, extra={"color_message": color_message}) + + await self.startup(sockets=sockets) + if self.should_exit: + return + await self.main_loop() + await self.shutdown(sockets=sockets) + + message = "Finished server process [%d]" + color_message = "Finished server process [" + click.style("%d", fg="cyan") + "]" + logger.info(message, process_id, extra={"color_message": color_message}) + + async def startup(self, sockets: list = None) -> None: + await self.lifespan.startup() + if self.lifespan.should_exit: + self.should_exit = True + return + + config = self.config + + create_protocol = functools.partial( + config.http_protocol_class, config=config, server_state=self.server_state + ) + loop = asyncio.get_running_loop() + + listeners: Sequence[socket.SocketType] + if sockets is not None: + # Explicitly passed a list of open sockets. + # We use this when the server is run from a Gunicorn worker. + + def _share_socket(sock: socket.SocketType) -> socket.SocketType: + # Windows requires the socket be explicitly shared across + # multiple workers (processes). + from socket import fromshare # type: ignore + + sock_data = sock.share(os.getpid()) # type: ignore + return fromshare(sock_data) + + self.servers = [] + for sock in sockets: + if config.workers > 1 and platform.system() == "Windows": + sock = _share_socket(sock) + server = await loop.create_server( + create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog + ) + self.servers.append(server) + listeners = sockets + + elif config.fd is not None: + # Use an existing socket, from a file descriptor. + sock = socket.fromfd(config.fd, socket.AF_UNIX, socket.SOCK_STREAM) + server = await loop.create_server( + create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog + ) + assert server.sockets is not None # mypy + listeners = server.sockets + self.servers = [server] + + elif config.uds is not None: + # Create a socket using UNIX domain socket. + uds_perms = 0o666 + if os.path.exists(config.uds): + uds_perms = os.stat(config.uds).st_mode + server = await loop.create_unix_server( + create_protocol, path=config.uds, ssl=config.ssl, backlog=config.backlog + ) + os.chmod(config.uds, uds_perms) + assert server.sockets is not None # mypy + listeners = server.sockets + self.servers = [server] + + else: + # Standard case. Create a socket from a host/port pair. + try: + server = await loop.create_server( + create_protocol, + host=config.host, + port=config.port, + ssl=config.ssl, + backlog=config.backlog, + ) + except OSError as exc: + logger.error(exc) + await self.lifespan.shutdown() + sys.exit(1) + + assert server.sockets is not None + listeners = server.sockets + self.servers = [server] + + if sockets is None: + self._log_started_message(listeners) + else: + # We're most likely running multiple workers, so a message has already been + # logged by `config.bind_socket()`. + pass + + self.started = True + + def _log_started_message(self, listeners: Sequence[socket.SocketType]) -> None: + config = self.config + + if config.fd is not None: + sock = listeners[0] + logger.info( + "Uvicorn running on socket %s (Press CTRL+C to quit)", + sock.getsockname(), + ) + + elif config.uds is not None: + logger.info( + "Uvicorn running on unix socket %s (Press CTRL+C to quit)", config.uds + ) + + else: + addr_format = "%s://%s:%d" + host = "0.0.0.0" if config.host is None else config.host + if ":" in host: + # It's an IPv6 address. + addr_format = "%s://[%s]:%d" + + port = config.port + if port == 0: + port = listeners[0].getsockname()[1] + + protocol_name = "https" if config.ssl else "http" + message = f"Uvicorn running on {addr_format} (Press CTRL+C to quit)" + color_message = ( + "Uvicorn running on " + + click.style(addr_format, bold=True) + + " (Press CTRL+C to quit)" + ) + logger.info( + message, + protocol_name, + host, + port, + extra={"color_message": color_message}, + ) + + async def main_loop(self) -> None: + counter = 0 + should_exit = await self.on_tick(counter) + while not should_exit: + counter += 1 + counter = counter % 864000 + await asyncio.sleep(0.1) + should_exit = await self.on_tick(counter) + + async def on_tick(self, counter: int) -> bool: + # Update the default headers, once per second. + if counter % 10 == 0: + current_time = time.time() + current_date = formatdate(current_time, usegmt=True).encode() + + if self.config.date_header: + date_header = [(b"date", current_date)] + else: + date_header = [] + + self.server_state.default_headers = ( + date_header + self.config.encoded_headers + ) + + # Callback to `callback_notify` once every `timeout_notify` seconds. + if self.config.callback_notify is not None: + if current_time - self.last_notified > self.config.timeout_notify: + self.last_notified = current_time + await self.config.callback_notify() + + # Determine if we should exit. + if self.should_exit: + return True + if self.config.limit_max_requests is not None: + return self.server_state.total_requests >= self.config.limit_max_requests + return False + + async def shutdown(self, sockets: Optional[List[socket.socket]] = None) -> None: + logger.info("Shutting down") + + # Stop accepting new connections. + for server in self.servers: + server.close() + for sock in sockets or []: + sock.close() + for server in self.servers: + await server.wait_closed() + + # Request shutdown on all existing connections. + for connection in list(self.server_state.connections): + connection.shutdown() + await asyncio.sleep(0.1) + + # Wait for existing connections to finish sending responses. + if self.server_state.connections and not self.force_exit: + msg = "Waiting for connections to close. (CTRL+C to force quit)" + logger.info(msg) + while self.server_state.connections and not self.force_exit: + await asyncio.sleep(0.1) + + # Wait for existing tasks to complete. + if self.server_state.tasks and not self.force_exit: + msg = "Waiting for background tasks to complete. (CTRL+C to force quit)" + logger.info(msg) + while self.server_state.tasks and not self.force_exit: + await asyncio.sleep(0.1) + + # Send the lifespan shutdown event, and wait for application shutdown. + if not self.force_exit: + await self.lifespan.shutdown() + + def install_signal_handlers(self) -> None: + if threading.current_thread() is not threading.main_thread(): + # Signals can only be listened to from the main thread. + return + + loop = asyncio.get_event_loop() + + try: + for sig in HANDLED_SIGNALS: + loop.add_signal_handler(sig, self.handle_exit, sig, None) + except NotImplementedError: # pragma: no cover + # Windows + for sig in HANDLED_SIGNALS: + signal.signal(sig, self.handle_exit) + + def handle_exit(self, sig: int, frame: Optional[FrameType]) -> None: + + if self.should_exit and sig == signal.SIGINT: + self.force_exit = True + else: + self.should_exit = True diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/__init__.py new file mode 100644 index 00000000..deaf12ed --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/__init__.py @@ -0,0 +1,21 @@ +from typing import TYPE_CHECKING, Type + +from uvicorn.supervisors.basereload import BaseReload +from uvicorn.supervisors.multiprocess import Multiprocess + +if TYPE_CHECKING: + ChangeReload: Type[BaseReload] +else: + try: + from uvicorn.supervisors.watchfilesreload import ( + WatchFilesReload as ChangeReload, + ) + except ImportError: # pragma: no cover + try: + from uvicorn.supervisors.watchgodreload import ( + WatchGodReload as ChangeReload, + ) + except ImportError: + from uvicorn.supervisors.statreload import StatReload as ChangeReload + +__all__ = ["Multiprocess", "ChangeReload"] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/basereload.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/basereload.py new file mode 100644 index 00000000..b2d80d3e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/basereload.py @@ -0,0 +1,113 @@ +import logging +import os +import signal +import threading +from pathlib import Path +from socket import socket +from types import FrameType +from typing import Callable, Iterator, List, Optional + +import click + +from uvicorn._subprocess import get_subprocess +from uvicorn.config import Config + +HANDLED_SIGNALS = ( + signal.SIGINT, # Unix signal 2. Sent by Ctrl+C. + signal.SIGTERM, # Unix signal 15. Sent by `kill `. +) + +logger = logging.getLogger("uvicorn.error") + + +class BaseReload: + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + self.config = config + self.target = target + self.sockets = sockets + self.should_exit = threading.Event() + self.pid = os.getpid() + self.reloader_name: Optional[str] = None + + def signal_handler(self, sig: int, frame: Optional[FrameType]) -> None: + """ + A signal handler that is registered with the parent process. + """ + self.should_exit.set() + + def run(self) -> None: + self.startup() + for changes in self: + if changes: + logger.warning( + "%s detected changes in %s. Reloading...", + self.reloader_name, + ", ".join(map(_display_path, changes)), + ) + self.restart() + + self.shutdown() + + def pause(self) -> None: + if self.should_exit.wait(self.config.reload_delay): + raise StopIteration() + + def __iter__(self) -> Iterator[Optional[List[Path]]]: + return self + + def __next__(self) -> Optional[List[Path]]: + return self.should_restart() + + def startup(self) -> None: + message = f"Started reloader process [{self.pid}] using {self.reloader_name}" + color_message = "Started reloader process [{}] using {}".format( + click.style(str(self.pid), fg="cyan", bold=True), + click.style(str(self.reloader_name), fg="cyan", bold=True), + ) + logger.info(message, extra={"color_message": color_message}) + + for sig in HANDLED_SIGNALS: + signal.signal(sig, self.signal_handler) + + self.process = get_subprocess( + config=self.config, target=self.target, sockets=self.sockets + ) + self.process.start() + + def restart(self) -> None: + + self.process.terminate() + self.process.join() + + self.process = get_subprocess( + config=self.config, target=self.target, sockets=self.sockets + ) + self.process.start() + + def shutdown(self) -> None: + self.process.terminate() + self.process.join() + + for sock in self.sockets: + sock.close() + + message = "Stopping reloader process [{}]".format(str(self.pid)) + color_message = "Stopping reloader process [{}]".format( + click.style(str(self.pid), fg="cyan", bold=True) + ) + logger.info(message, extra={"color_message": color_message}) + + def should_restart(self) -> Optional[List[Path]]: + raise NotImplementedError("Reload strategies should override should_restart()") + + +def _display_path(path: Path) -> str: + try: + return f"'{path.relative_to(Path.cwd())}'" + except ValueError: + return f"'{path}'" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/multiprocess.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/multiprocess.py new file mode 100644 index 00000000..9ab4a742 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/multiprocess.py @@ -0,0 +1,74 @@ +import logging +import os +import signal +import threading +from multiprocessing.context import SpawnProcess +from socket import socket +from types import FrameType +from typing import Callable, List, Optional + +import click + +from uvicorn._subprocess import get_subprocess +from uvicorn.config import Config + +HANDLED_SIGNALS = ( + signal.SIGINT, # Unix signal 2. Sent by Ctrl+C. + signal.SIGTERM, # Unix signal 15. Sent by `kill `. +) + +logger = logging.getLogger("uvicorn.error") + + +class Multiprocess: + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + self.config = config + self.target = target + self.sockets = sockets + self.processes: List[SpawnProcess] = [] + self.should_exit = threading.Event() + self.pid = os.getpid() + + def signal_handler(self, sig: int, frame: Optional[FrameType]) -> None: + """ + A signal handler that is registered with the parent process. + """ + self.should_exit.set() + + def run(self) -> None: + self.startup() + self.should_exit.wait() + self.shutdown() + + def startup(self) -> None: + message = "Started parent process [{}]".format(str(self.pid)) + color_message = "Started parent process [{}]".format( + click.style(str(self.pid), fg="cyan", bold=True) + ) + logger.info(message, extra={"color_message": color_message}) + + for sig in HANDLED_SIGNALS: + signal.signal(sig, self.signal_handler) + + for idx in range(self.config.workers): + process = get_subprocess( + config=self.config, target=self.target, sockets=self.sockets + ) + process.start() + self.processes.append(process) + + def shutdown(self) -> None: + for process in self.processes: + process.terminate() + process.join() + + message = "Stopping parent process [{}]".format(str(self.pid)) + color_message = "Stopping parent process [{}]".format( + click.style(str(self.pid), fg="cyan", bold=True) + ) + logger.info(message, extra={"color_message": color_message}) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/statreload.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/statreload.py new file mode 100644 index 00000000..7cbcce31 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/statreload.py @@ -0,0 +1,53 @@ +import logging +from pathlib import Path +from socket import socket +from typing import Callable, Dict, Iterator, List, Optional + +from uvicorn.config import Config +from uvicorn.supervisors.basereload import BaseReload + +logger = logging.getLogger("uvicorn.error") + + +class StatReload(BaseReload): + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + super().__init__(config, target, sockets) + self.reloader_name = "StatReload" + self.mtimes: Dict[Path, float] = {} + + if config.reload_excludes or config.reload_includes: + logger.warning( + "--reload-include and --reload-exclude have no effect unless " + "watchfiles is installed." + ) + + def should_restart(self) -> Optional[List[Path]]: + self.pause() + + for file in self.iter_py_files(): + try: + mtime = file.stat().st_mtime + except OSError: # pragma: nocover + continue + + old_time = self.mtimes.get(file) + if old_time is None: + self.mtimes[file] = mtime + continue + elif mtime > old_time: + return [file] + return None + + def restart(self) -> None: + self.mtimes = {} + return super().restart() + + def iter_py_files(self) -> Iterator[Path]: + for reload_dir in self.config.reload_dirs: + for path in list(reload_dir.rglob("*.py")): + yield path.resolve() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchfilesreload.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchfilesreload.py new file mode 100644 index 00000000..9ba10ce9 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchfilesreload.py @@ -0,0 +1,89 @@ +from pathlib import Path +from socket import socket +from typing import Callable, List, Optional + +from watchfiles import watch + +from uvicorn.config import Config +from uvicorn.supervisors.basereload import BaseReload + + +class FileFilter: + def __init__(self, config: Config): + default_includes = ["*.py"] + self.includes = [ + default + for default in default_includes + if default not in config.reload_excludes + ] + self.includes.extend(config.reload_includes) + self.includes = list(set(self.includes)) + + default_excludes = [".*", ".py[cod]", ".sw.*", "~*"] + self.excludes = [ + default + for default in default_excludes + if default not in config.reload_includes + ] + self.exclude_dirs = [] + for e in config.reload_excludes: + p = Path(e) + try: + is_dir = p.is_dir() + except OSError: # pragma: no cover + # gets raised on Windows for values like "*.py" + is_dir = False + + if is_dir: + self.exclude_dirs.append(p) + else: + self.excludes.append(e) + self.excludes = list(set(self.excludes)) + + def __call__(self, path: Path) -> bool: + for include_pattern in self.includes: + if path.match(include_pattern): + for exclude_dir in self.exclude_dirs: + if exclude_dir in path.parents: + return False + + for exclude_pattern in self.excludes: + if path.match(exclude_pattern): + return False + + return True + return False + + +class WatchFilesReload(BaseReload): + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + super().__init__(config, target, sockets) + self.reloader_name = "WatchFiles" + self.reload_dirs = [] + for directory in config.reload_dirs: + if Path.cwd() not in directory.parents: + self.reload_dirs.append(directory) + if Path.cwd() not in self.reload_dirs: + self.reload_dirs.append(Path.cwd()) + + self.watch_filter = FileFilter(config) + self.watcher = watch( + *self.reload_dirs, + watch_filter=None, + stop_event=self.should_exit, + # using yield_on_timeout here mostly to make sure tests don't + # hang forever, won't affect the class's behavior + yield_on_timeout=True, + ) + + def should_restart(self) -> Optional[List[Path]]: + changes = next(self.watcher) + if changes: + unique_paths = {Path(c[1]) for c in changes} + return [p for p in unique_paths if self.watch_filter(p)] + return None diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchgodreload.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchgodreload.py new file mode 100644 index 00000000..1ec3dc59 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/supervisors/watchgodreload.py @@ -0,0 +1,158 @@ +import logging +import warnings +from pathlib import Path +from socket import socket +from typing import TYPE_CHECKING, Callable, Dict, List, Optional + +from watchgod import DefaultWatcher + +from uvicorn.config import Config +from uvicorn.supervisors.basereload import BaseReload + +if TYPE_CHECKING: + import os + + DirEntry = os.DirEntry[str] + +logger = logging.getLogger("uvicorn.error") + + +class CustomWatcher(DefaultWatcher): + def __init__(self, root_path: Path, config: Config): + default_includes = ["*.py"] + self.includes = [ + default + for default in default_includes + if default not in config.reload_excludes + ] + self.includes.extend(config.reload_includes) + self.includes = list(set(self.includes)) + + default_excludes = [".*", ".py[cod]", ".sw.*", "~*"] + self.excludes = [ + default + for default in default_excludes + if default not in config.reload_includes + ] + self.excludes.extend(config.reload_excludes) + self.excludes = list(set(self.excludes)) + + self.watched_dirs: Dict[str, bool] = {} + self.watched_files: Dict[str, bool] = {} + self.dirs_includes = set(config.reload_dirs) + self.dirs_excludes = set(config.reload_dirs_excludes) + self.resolved_root = root_path + super().__init__(str(root_path)) + + def should_watch_file(self, entry: "DirEntry") -> bool: + cached_result = self.watched_files.get(entry.path) + if cached_result is not None: + return cached_result + + entry_path = Path(entry) + + # cwd is not verified through should_watch_dir, so we need to verify here + if entry_path.parent == Path.cwd() and not Path.cwd() in self.dirs_includes: + self.watched_files[entry.path] = False + return False + for include_pattern in self.includes: + if entry_path.match(include_pattern): + for exclude_pattern in self.excludes: + if entry_path.match(exclude_pattern): + self.watched_files[entry.path] = False + return False + self.watched_files[entry.path] = True + return True + self.watched_files[entry.path] = False + return False + + def should_watch_dir(self, entry: "DirEntry") -> bool: + cached_result = self.watched_dirs.get(entry.path) + if cached_result is not None: + return cached_result + + entry_path = Path(entry) + + if entry_path in self.dirs_excludes: + self.watched_dirs[entry.path] = False + return False + + for exclude_pattern in self.excludes: + if entry_path.match(exclude_pattern): + is_watched = False + if entry_path in self.dirs_includes: + is_watched = True + + for directory in self.dirs_includes: + if directory in entry_path.parents: + is_watched = True + + if is_watched: + logger.debug( + "WatchGodReload detected a new excluded dir '%s' in '%s'; " + "Adding to exclude list.", + entry_path.relative_to(self.resolved_root), + str(self.resolved_root), + ) + self.watched_dirs[entry.path] = False + self.dirs_excludes.add(entry_path) + return False + + if entry_path in self.dirs_includes: + self.watched_dirs[entry.path] = True + return True + + for directory in self.dirs_includes: + if directory in entry_path.parents: + self.watched_dirs[entry.path] = True + return True + + for include_pattern in self.includes: + if entry_path.match(include_pattern): + logger.info( + "WatchGodReload detected a new reload dir '%s' in '%s'; " + "Adding to watch list.", + str(entry_path.relative_to(self.resolved_root)), + str(self.resolved_root), + ) + self.dirs_includes.add(entry_path) + self.watched_dirs[entry.path] = True + return True + + self.watched_dirs[entry.path] = False + return False + + +class WatchGodReload(BaseReload): + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + warnings.warn( + '"watchgod" is depreciated, you should switch ' + "to watchfiles (`pip install watchfiles`).", + DeprecationWarning, + ) + super().__init__(config, target, sockets) + self.reloader_name = "WatchGod" + self.watchers = [] + reload_dirs = [] + for directory in config.reload_dirs: + if Path.cwd() not in directory.parents: + reload_dirs.append(directory) + if Path.cwd() not in reload_dirs: + reload_dirs.append(Path.cwd()) + for w in reload_dirs: + self.watchers.append(CustomWatcher(w.resolve(), self.config)) + + def should_restart(self) -> Optional[List[Path]]: + self.pause() + + for watcher in self.watchers: + change = watcher.check() + if change != set(): + return list({Path(c[1]) for c in change}) + + return None diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/workers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/workers.py new file mode 100644 index 00000000..f28c3a8d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/uvicorn/workers.py @@ -0,0 +1,90 @@ +import asyncio +import logging +import signal +import sys +from typing import Any + +from gunicorn.arbiter import Arbiter +from gunicorn.workers.base import Worker + +from uvicorn.config import Config +from uvicorn.main import Server + + +class UvicornWorker(Worker): + """ + A worker class for Gunicorn that interfaces with an ASGI consumer callable, + rather than a WSGI callable. + """ + + CONFIG_KWARGS = {"loop": "auto", "http": "auto"} + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super(UvicornWorker, self).__init__(*args, **kwargs) + + logger = logging.getLogger("uvicorn.error") + logger.handlers = self.log.error_log.handlers + logger.setLevel(self.log.error_log.level) + logger.propagate = False + + logger = logging.getLogger("uvicorn.access") + logger.handlers = self.log.access_log.handlers + logger.setLevel(self.log.access_log.level) + logger.propagate = False + + config_kwargs: dict = { + "app": None, + "log_config": None, + "timeout_keep_alive": self.cfg.keepalive, + "timeout_notify": self.timeout, + "callback_notify": self.callback_notify, + "limit_max_requests": self.max_requests, + "forwarded_allow_ips": self.cfg.forwarded_allow_ips, + } + + if self.cfg.is_ssl: + ssl_kwargs = { + "ssl_keyfile": self.cfg.ssl_options.get("keyfile"), + "ssl_certfile": self.cfg.ssl_options.get("certfile"), + "ssl_keyfile_password": self.cfg.ssl_options.get("password"), + "ssl_version": self.cfg.ssl_options.get("ssl_version"), + "ssl_cert_reqs": self.cfg.ssl_options.get("cert_reqs"), + "ssl_ca_certs": self.cfg.ssl_options.get("ca_certs"), + "ssl_ciphers": self.cfg.ssl_options.get("ciphers"), + } + config_kwargs.update(ssl_kwargs) + + if self.cfg.settings["backlog"].value: + config_kwargs["backlog"] = self.cfg.settings["backlog"].value + + config_kwargs.update(self.CONFIG_KWARGS) + + self.config = Config(**config_kwargs) + + def init_process(self) -> None: + self.config.setup_event_loop() + super(UvicornWorker, self).init_process() + + def init_signals(self) -> None: + # Reset signals so Gunicorn doesn't swallow subprocess return codes + # other signals are set up by Server.install_signal_handlers() + # See: https://github.com/encode/uvicorn/issues/894 + for s in self.SIGNALS: + signal.signal(s, signal.SIG_DFL) + + async def _serve(self) -> None: + self.config.app = self.wsgi + server = Server(config=self.config) + await server.serve(sockets=self.sockets) + if not server.started: + sys.exit(Arbiter.WORKER_BOOT_ERROR) + + def run(self) -> None: + return asyncio.run(self._serve()) + + async def callback_notify(self) -> None: + self.notify() + + +class UvicornH11Worker(UvicornWorker): + CONFIG_KWARGS = {"loop": "asyncio", "http": "h11"} diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/METADATA new file mode 100644 index 00000000..440fb3df --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/METADATA @@ -0,0 +1,147 @@ +Metadata-Version: 2.1 +Name: watchfiles +Version: 0.16.1 +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: Microsoft :: Windows +Classifier: Operating System :: MacOS +Classifier: Environment :: MacOS X +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Filesystems +Classifier: Framework :: AnyIO +Requires-Dist: anyio>=3.0.0,<4 +License-File: LICENSE +Summary: Simple, modern and high performance file watching and code reload in python. +Author-email: Samuel Colvin +Requires-Python: >=3.7 +Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM +Project-URL: Source, https://github.com/samuelcolvin/watchfiles +Project-URL: Documentation, https://watchfiles.helpmanual.io +Project-URL: Homepage, https://github.com/samuelcolvin/watchfiles +Project-URL: Changelog, https://github.com/samuelcolvin/watchfiles/releases +Project-URL: Funding, https://github.com/sponsors/samuelcolvin + +# watchfiles + +[![CI](https://github.com/samuelcolvin/watchfiles/workflows/ci/badge.svg?event=push)](https://github.com/samuelcolvin/watchfiles/actions?query=event%3Apush+branch%3Amain+workflow%3Aci) +[![Coverage](https://codecov.io/gh/samuelcolvin/watchfiles/branch/main/graph/badge.svg)](https://codecov.io/gh/samuelcolvin/watchfiles) +[![pypi](https://img.shields.io/pypi/v/watchfiles.svg)](https://pypi.python.org/pypi/watchfiles) +[![license](https://img.shields.io/github/license/samuelcolvin/watchfiles.svg)](https://github.com/samuelcolvin/watchfiles/blob/main/LICENSE) + +Simple, modern and high performance file watching and code reload in python. + +--- + +**Documentation**: [watchfiles.helpmanual.io](https://watchfiles.helpmanual.io) + +**Source Code**: [github.com/samuelcolvin/watchfiles](https://github.com/samuelcolvin/watchfiles) + +--- + +Underlying file system notifications are handled by the [Notify](https://github.com/notify-rs/notify) rust library. + +This package was previously named "watchgod", +see [the migration guide](https://watchfiles.helpmanual.io/migrating/) for more information. + +## Installation + +**watchfiles** requires Python 3.7 - 3.10. + +```bash +pip install watchfiles +``` + +Binaries are available for: + +* **Linux**: `x86_64`, `aarch64`, `i686`, `armv7l`, `musl-x86_64` & `musl-aarch64` +* **MacOS**: `x86_64` & `arm64` (except python 3.7) +* **Windows**: `amd64` & `win32` + +Otherwise, you can install from source which requires Rust stable to be installed. + +## Usage + +Here are some examples of what **watchfiles** can do: + +### `watch` Usage + +```py +from watchfiles import watch + +for changes in watch('./path/to/dir'): + print(changes) +``` +See [`watch` docs](https://watchfiles.helpmanual.io/api/watch/#watchfiles.watch) for more details. + +### `awatch` Usage + +```py +import asyncio +from watchfiles import awatch + +async def main(): + async for changes in awatch('/path/to/dir'): + print(changes) + +asyncio.run(main()) +``` +See [`awatch` docs](https://watchfiles.helpmanual.io/api/watch/#watchfiles.awatch) for more details. + +### `run_process` Usage + +```py +from watchfiles import run_process + +def foobar(a, b, c): + ... + +if __name__ == '__main__': + run_process('./path/to/dir', target=foobar, args=(1, 2, 3)) +``` +See [`run_process` docs](https://watchfiles.helpmanual.io/api/run_process/#watchfiles.run_process) for more details. + +### `arun_process` Usage + +```py +import asyncio +from watchfiles import arun_process + +def foobar(a, b, c): + ... + +async def main(): + await arun_process('./path/to/dir', target=foobar, args=(1, 2, 3)) + +if __name__ == '__main__': + asyncio.run(main()) +``` +See [`arun_process` docs](https://watchfiles.helpmanual.io/api/run_process/#watchfiles.arun_process) for more details. + +## CLI + +**watchfiles** also comes with a CLI for running and reloading code. To run `some command` when files in `src` change: + +``` +watchfiles "some command" src +``` + +For more information, see [the CLI docs](https://watchfiles.helpmanual.io/cli/). + +Or run + +```bash +watchfiles --help +``` + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/RECORD new file mode 100644 index 00000000..30618337 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/RECORD @@ -0,0 +1,24 @@ +../../Scripts/watchfiles.exe,sha256=QMfA3FK0FohZfOOXT3n-LhY11W6YLdkWQ3IlhZhVqSc,106373 +watchfiles-0.16.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +watchfiles-0.16.1.dist-info/METADATA,sha256=WAH-hzuRX5vBZW4GH3HiTH_oLKSYiqURqB5iwl540go,4766 +watchfiles-0.16.1.dist-info/RECORD,, +watchfiles-0.16.1.dist-info/WHEEL,sha256=HxhXltn1XXIfoc5D9ilfTZkcDZBkaaDcRoY57WxHST8,95 +watchfiles-0.16.1.dist-info/entry_points.txt,sha256=s1Dpa2d_KKBy-jKREWW60Z3GoRZ3JpCEo_9iYDt6hOQ,48 +watchfiles-0.16.1.dist-info/license_files/LICENSE,sha256=OJNLTJ74C1LXy3zC9PxI5qMeL3k2sWtQawqK7bVd5iM,1131 +watchfiles/__init__.py,sha256=LKmDAbDbm78xfyhVQ-W_6TWfT1Cg53NUaHqNhwu2plo,381 +watchfiles/__main__.py,sha256=g9iBs8xxX6Yik7cmgllQkpBN8C4JNoZVsEOyCCLCyFU,63 +watchfiles/__pycache__/__init__.cpython-37.pyc,, +watchfiles/__pycache__/__main__.cpython-37.pyc,, +watchfiles/__pycache__/cli.cpython-37.pyc,, +watchfiles/__pycache__/filters.cpython-37.pyc,, +watchfiles/__pycache__/main.cpython-37.pyc,, +watchfiles/__pycache__/run.cpython-37.pyc,, +watchfiles/__pycache__/version.cpython-37.pyc,, +watchfiles/_rust_notify.pyd,sha256=TNFOOX4FqecXQT3qv16y-wVofCTbkhxstoUHBYDETMo,589824 +watchfiles/_rust_notify.pyi,sha256=7_SUkU-l5qcwllflsB_qa7pqPK9UZ0v5KPxlRqSb0Ho,4497 +watchfiles/cli.py,sha256=W0FsNws4RAujae4QfmoUzrz1pLeCUXh0mmHlC0AqdcQ,7207 +watchfiles/filters.py,sha256=56UwipWyHmOy9oWBQ0K9yEGcJMe-Xesf2W0njKeWtIk,5240 +watchfiles/main.py,sha256=XbwiubVOBgjCveTa4ny7qJnDR8G3q7gWdyZcveAlti8,11789 +watchfiles/py.typed,sha256=5_E2MNyI4Mzg8TH53HFdXg0iSevlmHpdZSNnJVUYbMg,70 +watchfiles/run.py,sha256=m9mWrHSbQTp9g6nNdN5JMI4GMl3MtRkk8QiWbGbobkA,13961 +watchfiles/version.py,sha256=dbZJrjIgVt2QedB7aWTu41SUWaPDjUCabWBao2Ow1SU,90 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/WHEEL new file mode 100644 index 00000000..df3f3487 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: maturin (0.13.0) +Root-Is-Purelib: false +Tag: cp37-abi3-win_amd64 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/entry_points.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/entry_points.txt new file mode 100644 index 00000000..51642969 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +watchfiles=watchfiles.cli:cli diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/license_files/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/license_files/LICENSE new file mode 100644 index 00000000..08c9a8d3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles-0.16.1.dist-info/license_files/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017, 2018, 2019, 2020, 2021, 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__init__.py new file mode 100644 index 00000000..877fbd57 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__init__.py @@ -0,0 +1,17 @@ +from .filters import BaseFilter, DefaultFilter, PythonFilter +from .main import Change, awatch, watch +from .run import arun_process, run_process +from .version import VERSION + +__version__ = VERSION +__all__ = ( + 'watch', + 'awatch', + 'run_process', + 'arun_process', + 'Change', + 'BaseFilter', + 'DefaultFilter', + 'PythonFilter', + 'VERSION', +) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__main__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__main__.py new file mode 100644 index 00000000..d396c2a7 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/__main__.py @@ -0,0 +1,4 @@ +from .cli import cli + +if __name__ == '__main__': + cli() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/_rust_notify.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/_rust_notify.pyd new file mode 100644 index 0000000000000000000000000000000000000000..b95a16fbd7081fc9076e4a6de12c4700ece3abde GIT binary patch literal 589824 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
      4{FCjWs^ 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
    1. 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
        s^t=(zrl1(8 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 z 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 b{!x^*KZG4Uluw$2Ib-4Q|NZy>(F6Yv^_Mxw literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/_rust_notify.pyi b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/_rust_notify.pyi new file mode 100644 index 00000000..cedeefc4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/_rust_notify.pyi @@ -0,0 +1,100 @@ +from typing import Any, List, Literal, Optional, Protocol, Set, Tuple, Union + +__all__ = 'RustNotify', 'WatchfilesRustInternalError' + +__version__: str +"""The package version as defined in `Cargo.toml`, modified to match python's versioning semantics.""" + +class AbstractEvent(Protocol): + def is_set(self) -> bool: ... + +class RustNotify: + """ + Interface to the Rust [notify](https://crates.io/crates/notify) crate which does + the heavy lifting of watching for file changes and grouping them into events. + """ + + def __init__(self, watch_paths: List[str], debug: bool, force_polling: bool, poll_delay_ms: int) -> None: + """ + Create a new `RustNotify` instance and start a thread to watch for changes. + + `FileNotFoundError` is raised if any of the paths do not exist. + + Args: + watch_paths: file system paths to watch for changes, can be directories or files + debug: if true, print details about all events to stderr + force_polling: if true, always use polling instead of file system notifications + poll_delay_ms: delay between polling for changes, only used if `force_polling=True` + """ + def watch( + self, + debounce_ms: int, + step_ms: int, + timeout_ms: int, + stop_event: Optional[AbstractEvent], + ) -> Union[Set[Tuple[int, str]], Literal['signal', 'stop', 'timeout']]: + """ + Watch for changes. + + This method will wait `timeout_ms` milliseconds for changes, but once a change is detected, + it will group changes and return in no more than `debounce_ms` milliseconds. + + The GIL is released during a `step_ms` sleep on each iteration to avoid + blocking python. + + Args: + debounce_ms: maximum time in milliseconds to group changes over before returning. + step_ms: time to wait for new changes in milliseconds, if no changes are detected + in this time, and at least one change has been detected, the changes are yielded. + timeout_ms: maximum time in milliseconds to wait for changes before returning, + `0` means wait indefinitely, `debounce_ms` takes precedence over `timeout_ms` once + a change is detected. + stop_event: event to check on every iteration to see if this function should return early. + The event should be an object which has an `is_set()` method which returns a boolean. + + Returns: + See below. + + Return values have the following meanings: + + * Change details as a `set` of `(event_type, path)` tuples, the event types are ints which match + [`Change`][watchfiles.Change], `path` is a string representing the path of the file that changed + * `'signal'` string, if a signal was received + * `'stop'` string, if the `stop_event` was set + * `'timeout'` string, if `timeout_ms` was exceeded + """ + def __enter__(self) -> 'RustNotify': + """ + Does nothing, but allows `RustNotify` to be used as a context manager. + + !!! note + + The watching thead is created when an instance is initiated, not on `__enter__`. + """ + def __exit__(self, *args: Any) -> None: + """ + Calls [`close`][watchfiles._rust_notify.RustNotify.close]. + """ + def close(self) -> None: + """ + Stops the watching thread. After `close` is called, the `RustNotify` instance can no + longer be used, calls to [`watch`][watchfiles._rust_notify.RustNotify.watch] will raise a `RuntimeError`. + + !!! note + + `close` is not required, just deleting the `RustNotify` instance will kill the thread + implicitly. + + As per [#163](https://github.com/samuelcolvin/watchfiles/issues/163) `close()` is only required because + in the event of an error, the traceback in `sys.exc_info` keeps a reference to `watchfiles.watch`'s + frame, so you can't rely on the `RustNotify` object being deleted, and thereby stopping + the watching thread. + """ + +class WatchfilesRustInternalError(RuntimeError): + """ + Raised when RustNotify encounters an unknown error. + + If you get this a lot, please check [github](https://github.com/samuelcolvin/watchfiles/issues) issues + and create a new issue if your problem is not discussed. + """ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/cli.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/cli.py new file mode 100644 index 00000000..d96dcf4f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/cli.py @@ -0,0 +1,206 @@ +import argparse +import logging +import os +import shlex +import sys +from pathlib import Path +from textwrap import dedent +from typing import Any, Callable, List, Optional, Tuple, Union, cast + +from . import Change +from .filters import BaseFilter, DefaultFilter, PythonFilter +from .run import detect_target_type, import_string, run_process +from .version import VERSION + +logger = logging.getLogger('watchfiles.cli') + + +def resolve_path(path_str: str) -> Path: + path = Path(path_str) + if not path.exists(): + raise FileNotFoundError(path) + else: + return path.resolve() + + +def cli(*args_: str) -> None: + """ + Watch one or more directories and execute either a shell command or a python function on file changes. + + Example of watching the current directory and calling a python function: + + watchfiles foobar.main + + Example of watching python files in two local directories and calling a shell command: + + watchfiles --filter python 'pytest --lf' src tests + + See https://watchfiles.helpmanual.io/cli/ for more information. + """ + args = args_ or sys.argv[1:] + parser = argparse.ArgumentParser( + prog='watchfiles', + description=dedent((cli.__doc__ or '').strip('\n')), + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument('target', help='Command or dotted function path to run') + parser.add_argument( + 'paths', nargs='*', default='.', help='Filesystem paths to watch, defaults to current directory' + ) + + parser.add_argument( + '--ignore-paths', + nargs='?', + type=str, + help=( + 'Specify directories to ignore, ' + 'to ignore multiple paths use a comma as separator, e.g. "env" or "env,node_modules"' + ), + ) + parser.add_argument( + '--target-type', + nargs='?', + type=str, + default='auto', + choices=['command', 'function', 'auto'], + help=( + 'Whether the target should be intercepted as a shell command or a python function, ' + 'defaults to "auto" which infers the target type from the target string' + ), + ) + parser.add_argument( + '--filter', + nargs='?', + type=str, + default='default', + help=( + 'Which files to watch, defaults to "default" which uses the "DefaultFilter", ' + '"python" uses the "PythonFilter", "all" uses no filter, ' + 'any other value is interpreted as a python function/class path which is imported' + ), + ) + parser.add_argument( + '--args', + nargs='?', + type=str, + help='Arguments to set on sys.argv before calling target function, used only if the target is a function', + ) + parser.add_argument('--verbose', action='store_true', help='Set log level to "debug", wins over `--verbosity`') + parser.add_argument( + '--verbosity', + nargs='?', + type=str, + default='info', + choices=['warning', 'info', 'debug'], + help='Log level, defaults to "info"', + ) + parser.add_argument( + '--sigint-timeout', + nargs='?', + type=int, + default=5, + help='How long to wait for the sigint timeout before sending sigkill.', + ) + parser.add_argument( + '--sigkill-timeout', + nargs='?', + type=int, + default=1, + help='How long to wait for the sigkill timeout before issuing a timeout exception.', + ) + parser.add_argument('--version', '-V', action='version', version=f'%(prog)s v{VERSION}') + arg_namespace = parser.parse_args(args) + + if arg_namespace.verbose: + log_level = logging.DEBUG + else: + log_level = getattr(logging, arg_namespace.verbosity.upper()) + + hdlr = logging.StreamHandler() + hdlr.setLevel(log_level) + hdlr.setFormatter(logging.Formatter(fmt='[%(asctime)s] %(message)s', datefmt='%H:%M:%S')) + wg_logger = logging.getLogger('watchfiles') + wg_logger.addHandler(hdlr) + wg_logger.setLevel(log_level) + + if arg_namespace.target_type == 'auto': + target_type = detect_target_type(arg_namespace.target) + else: + target_type = arg_namespace.target_type + + if target_type == 'function': + logger.debug('target_type=function, attempting import of "%s"', arg_namespace.target) + import_exit(arg_namespace.target) + if arg_namespace.args: + sys.argv = [arg_namespace.target] + shlex.split(arg_namespace.args) + elif arg_namespace.args: + logger.warning('--args is only used when the target is a function') + + try: + paths = [resolve_path(p) for p in arg_namespace.paths] + except FileNotFoundError as e: + print(f'path "{e}" does not exist', file=sys.stderr) + sys.exit(1) + + watch_filter, watch_filter_str = build_filter(arg_namespace.filter, arg_namespace.ignore_paths) + + logger.info( + 'watchfiles v%s 👀 path=%s target="%s" (%s) filter=%s...', + VERSION, + ', '.join(f'"{p}"' for p in paths), + arg_namespace.target, + target_type, + watch_filter_str, + ) + + run_process( + *paths, + target=arg_namespace.target, + target_type=target_type, + watch_filter=watch_filter, + debug=log_level == logging.DEBUG, + sigint_timeout=arg_namespace.sigint_timeout, + sigkill_timeout=arg_namespace.sigkill_timeout, + ) + + +def import_exit(function_path: str) -> Any: + cwd = os.getcwd() + if cwd not in sys.path: + sys.path.append(cwd) + + try: + return import_string(function_path) + except ImportError as e: + print(f'ImportError: {e}', file=sys.stderr) + sys.exit(1) + + +def build_filter( + filter_name: str, ignore_paths_str: Optional[str] +) -> Tuple[Union[None, DefaultFilter, Callable[[Change, str], bool]], str]: + ignore_paths: List[Path] = [] + if ignore_paths_str: + ignore_paths = [Path(p).resolve() for p in ignore_paths_str.split(',')] + + if filter_name == 'default': + return DefaultFilter(ignore_paths=ignore_paths), 'DefaultFilter' + elif filter_name == 'python': + return PythonFilter(ignore_paths=ignore_paths), 'PythonFilter' + elif filter_name == 'all': + if ignore_paths: + logger.warning('"--ignore-paths" argument ignored as "all" filter was selected') + return None, '(no filter)' + + watch_filter_cls = import_exit(filter_name) + if isinstance(watch_filter_cls, type) and issubclass(watch_filter_cls, DefaultFilter): + return watch_filter_cls(ignore_paths=ignore_paths), watch_filter_cls.__name__ + + if ignore_paths: + logger.warning('"--ignore-paths" argument ignored as filter is not a subclass of DefaultFilter') + + if isinstance(watch_filter_cls, type) and issubclass(watch_filter_cls, BaseFilter): + return watch_filter_cls(), watch_filter_cls.__name__ + else: + watch_filter = cast(Callable[[Change, str], bool], watch_filter_cls) + return watch_filter, repr(watch_filter_cls) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/filters.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/filters.py new file mode 100644 index 00000000..a55bf223 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/filters.py @@ -0,0 +1,147 @@ +import logging +import os +import re +from pathlib import Path +from typing import TYPE_CHECKING, Optional, Sequence, Union + +__all__ = 'BaseFilter', 'DefaultFilter', 'PythonFilter' +logger = logging.getLogger('watchfiles.watcher') + + +if TYPE_CHECKING: + from .main import Change + + +class BaseFilter: + """ + Useful base class for creating filters. `BaseFilter` should be inherited and configured, rather than used + directly. + + The class supports ignoring files in 3 ways: + """ + + __slots__ = '_ignore_dirs', '_ignore_entity_regexes', '_ignore_paths' + ignore_dirs: Sequence[str] = () + """Full names of directories to ignore, an obvious example would be `.git`.""" + ignore_entity_patterns: Sequence[str] = () + """ + Patterns of files or directories to ignore, these are compiled into regexes. + + "entity" here refers to the specific file or directory - basically the result of `path.split(os.sep)[-1]`, + an obvious example would be `r'\\.py[cod]$'`. + """ + ignore_paths: Sequence[Union[str, Path]] = () + """ + Full paths to ignore, e.g. `/home/users/.cache` or `C:\\Users\\user\\.cache`. + """ + + def __init__(self) -> None: + self._ignore_dirs = set(self.ignore_dirs) + self._ignore_entity_regexes = tuple(re.compile(r) for r in self.ignore_entity_patterns) + self._ignore_paths = tuple(map(str, self.ignore_paths)) + + def __call__(self, change: 'Change', path: str) -> bool: + """ + Instances of `BaseFilter` subclasses can be used as callables. + Args: + change: The type of change that occurred, see [`Change`][watchfiles.Change]. + path: the raw path of the file or directory that changed. + + Returns: + True if the file should be included in changes, False if it should be ignored. + """ + parts = path.lstrip(os.sep).split(os.sep) + if any(p in self._ignore_dirs for p in parts): + return False + + entity_name = parts[-1] + if any(r.search(entity_name) for r in self._ignore_entity_regexes): + return False + elif self._ignore_paths and path.startswith(self._ignore_paths): + return False + else: + return True + + def __repr__(self) -> str: + args = ', '.join(f'{k}={getattr(self, k, None)!r}' for k in self.__slots__) + return f'{self.__class__.__name__}({args})' + + +class DefaultFilter(BaseFilter): + """ + The default filter, which ignores files and directories that you might commonly want to ignore. + """ + + ignore_dirs: Sequence[str] = ( + '__pycache__', + '.git', + '.hg', + '.svn', + '.tox', + '.venv', + 'site-packages', + '.idea', + 'node_modules', + ) + """Directory names to ignore.""" + + ignore_entity_patterns: Sequence[str] = ( + r'\.py[cod]$', + r'\.___jb_...___$', + r'\.sw.$', + '~$', + r'^\.\#', + r'^\.DS_Store$', + r'^flycheck_', + ) + """File/Directory name patterns to ignore.""" + + def __init__( + self, + *, + ignore_dirs: Optional[Sequence[str]] = None, + ignore_entity_patterns: Optional[Sequence[str]] = None, + ignore_paths: Optional[Sequence[Union[str, Path]]] = None, + ) -> None: + """ + Args: + ignore_dirs: if not `None`, overrides the `ignore_dirs` value set on the class. + ignore_entity_patterns: if not `None`, overrides the `ignore_entity_patterns` value set on the class. + ignore_paths: if not `None`, overrides the `ignore_paths` value set on the class. + """ + if ignore_dirs is not None: + self.ignore_dirs = ignore_dirs + if ignore_entity_patterns is not None: + self.ignore_entity_patterns = ignore_entity_patterns + if ignore_paths is not None: + self.ignore_paths = ignore_paths + + super().__init__() + + +class PythonFilter(DefaultFilter): + """ + A filter for Python files, since this class inherits from [`DefaultFilter`][watchfiles.DefaultFilter] + it will ignore files and directories that you might commonly want to ignore as well as filtering out + all changes except in Python files (files with extensions `('.py', '.pyx', '.pyd')`). + """ + + def __init__( + self, + *, + ignore_paths: Optional[Sequence[Union[str, Path]]] = None, + extra_extensions: Sequence[str] = (), + ) -> None: + """ + Args: + ignore_paths: The paths to ignore, see [`BaseFilter`][watchfiles.BaseFilter]. + extra_extensions: extra extensions to ignore. + + `ignore_paths` and `extra_extensions` can be passed as arguments partly to support [CLI](../cli.md) usage where + `--ignore-paths` and `--extensions` can be passed as arguments. + """ + self.extensions = ('.py', '.pyx', '.pyd') + tuple(extra_extensions) + super().__init__(ignore_paths=ignore_paths) + + def __call__(self, change: 'Change', path: str) -> bool: + return path.endswith(self.extensions) and super().__call__(change, path) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/main.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/main.py new file mode 100644 index 00000000..7af2796a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/main.py @@ -0,0 +1,293 @@ +import logging +import os +import sys +import warnings +from enum import IntEnum +from pathlib import Path +from typing import TYPE_CHECKING, AsyncGenerator, Callable, Generator, Optional, Set, Tuple, Union + +import anyio + +from ._rust_notify import RustNotify +from .filters import DefaultFilter + +__all__ = 'watch', 'awatch', 'Change', 'FileChange' +logger = logging.getLogger('watchfiles.main') + + +class Change(IntEnum): + """ + Enum representing the type of change that occurred. + """ + + added = 1 + """A new file or directory was added.""" + modified = 2 + """A file or directory was modified, can be either a metadata or data change.""" + deleted = 3 + """A file or directory was deleted.""" + + def raw_str(self) -> str: + if self == Change.added: + return 'added' + elif self == Change.modified: + return 'modified' + else: + return 'deleted' + + +FileChange = Tuple[Change, str] +""" +A tuple representing a file change, first element is a [`Change`][watchfiles.Change] member, second is the path +of the file or directory that changed. +""" + +if TYPE_CHECKING: + import asyncio + from typing import Protocol + + import trio + + AnyEvent = Union[anyio.Event, asyncio.Event, trio.Event] + + class AbstractEvent(Protocol): + def is_set(self) -> bool: + ... + + +def watch( + *paths: Union[Path, str], + watch_filter: Optional[Callable[['Change', str], bool]] = DefaultFilter(), + debounce: int = 1_600, + step: int = 50, + stop_event: Optional['AbstractEvent'] = None, + rust_timeout: int = 5_000, + yield_on_timeout: bool = False, + debug: bool = False, + raise_interrupt: bool = True, + force_polling: Optional[bool] = None, + poll_delay_ms: int = 30, +) -> Generator[Set[FileChange], None, None]: + """ + Watch one or more paths and yield a set of changes whenever files change. + + The paths watched can be directories or files, directories are watched recursively - changes in subdirectories + are also detected. + + Args: + *paths: filesystem paths to watch. + watch_filter: callable used to filter out changes which are not important, you can either use a raw callable + or a [`BaseFilter`][watchfiles.BaseFilter] instance, + defaults to an instance of [`DefaultFilter`][watchfiles.DefaultFilter]. To keep all changes, use `None`. + debounce: maximum time in milliseconds to group changes over before yielding them. + step: time to wait for new changes in milliseconds, if no changes are detected in this time, and + at least one change has been detected, the changes are yielded. + stop_event: event to stop watching, if this is set, the generator will stop iteration, + this can be anything with an `is_set()` method which returns a bool, e.g. `threading.Event()`. + rust_timeout: maximum time in milliseconds to wait in the rust code for changes, `0` means no timeout. + yield_on_timeout: if `True`, the generator will yield upon timeout in rust even if no changes are detected. + debug: whether to print information about all filesystem changes in rust to stdout. + raise_interrupt: whether to re-raise `KeyboardInterrupt`s, or suppress the error and just stop iterating. + force_polling: if `True`, always use polling instead of file system notifications, default is `None` where + `force_polling` is set to `True` if the `WATCHFILES_FORCE_POLLING` environment variable exists. + poll_delay_ms: delay between polling for changes, only used if `force_polling=True`. + + Yields: + The generator yields sets of [`FileChange`][watchfiles.main.FileChange]s. + + ```py title="Example of watch usage" + from watchfiles import watch + + for changes in watch('./first/dir', './second/dir', raise_interrupt=False): + print(changes) + ``` + """ + force_polling = _default_force_pulling(force_polling) + with RustNotify([str(p) for p in paths], debug, force_polling, poll_delay_ms) as watcher: + while True: + raw_changes = watcher.watch(debounce, step, rust_timeout, stop_event) + if raw_changes == 'timeout': + if yield_on_timeout: + yield set() + else: + logger.debug('rust notify timeout, continuing') + elif raw_changes == 'signal': + if raise_interrupt: + raise KeyboardInterrupt + else: + logger.warning('KeyboardInterrupt caught, stopping watch') + return + elif raw_changes == 'stop': + return + else: + changes = _prep_changes(raw_changes, watch_filter) + if changes: + _log_changes(changes) + yield changes + + +async def awatch( # noqa C901 + *paths: Union[Path, str], + watch_filter: Optional[Callable[[Change, str], bool]] = DefaultFilter(), + debounce: int = 1_600, + step: int = 50, + stop_event: Optional['AnyEvent'] = None, + rust_timeout: Optional[int] = None, + yield_on_timeout: bool = False, + debug: bool = False, + raise_interrupt: Optional[bool] = None, + force_polling: Optional[bool] = None, + poll_delay_ms: int = 30, +) -> AsyncGenerator[Set[FileChange], None]: + """ + Asynchronous equivalent of [`watch`][watchfiles.watch] using threads to wait for changes. + Arguments match those of [`watch`][watchfiles.watch] except `stop_event`. + + All async methods use [anyio](https://anyio.readthedocs.io/en/latest/) to run the event loop. + + Unlike [`watch`][watchfiles.watch] `KeyboardInterrupt` cannot be suppressed by `awatch` so they need to be caught + where `asyncio.run` or equivalent is called. + + Args: + *paths: filesystem paths to watch. + watch_filter: matches the same argument of [`watch`][watchfiles.watch]. + debounce: matches the same argument of [`watch`][watchfiles.watch]. + step: matches the same argument of [`watch`][watchfiles.watch]. + stop_event: `anyio.Event` which can be used to stop iteration, see example below. + rust_timeout: matches the same argument of [`watch`][watchfiles.watch], except that `None` means + use `1_000` on Windows and `5_000` on other platforms thus helping with exiting on `Ctrl+C` on Windows, + see [#110](https://github.com/samuelcolvin/watchfiles/issues/110). + yield_on_timeout: matches the same argument of [`watch`][watchfiles.watch]. + debug: matches the same argument of [`watch`][watchfiles.watch]. + raise_interrupt: This is deprecated, `KeyboardInterrupt` will cause this coroutine to be cancelled and then + be raised by the top level `asyncio.run` call or equivalent, and should be caught there. + See [#136](https://github.com/samuelcolvin/watchfiles/issues/136) + force_polling: if true, always use polling instead of file system notifications, default is `None` where + `force_polling` is set to `True` if the `WATCHFILES_FORCE_POLLING` environment variable exists. + poll_delay_ms: delay between polling for changes, only used if `force_polling=True`. + + Yields: + The generator yields sets of [`FileChange`][watchfiles.main.FileChange]s. + + ```py title="Example of awatch usage" + import asyncio + from watchfiles import awatch + + async def main(): + async for changes in awatch('./first/dir', './second/dir'): + print(changes) + + if __name__ == '__main__': + try: + asyncio.run(main()) + except KeyboardInterrupt: + print('stopped via KeyboardInterrupt') + ``` + + ```py title="Example of awatch usage with a stop event" + import asyncio + from watchfiles import awatch + + async def main(): + stop_event = asyncio.Event() + + async def stop_soon(): + await asyncio.sleep(3) + stop_event.set() + + stop_soon_task = asyncio.create_task(stop_soon()) + + async for changes in awatch('/path/to/dir', stop_event=stop_event): + print(changes) + + # cleanup by awaiting the (now complete) stop_soon_task + await stop_soon_task + + asyncio.run(main()) + ``` + """ + if raise_interrupt is not None: + warnings.warn( + 'raise_interrupt is deprecated, KeyboardInterrupt will cause this coroutine to be cancelled and then ' + 'be raised by the top level asyncio.run call or equivalent, and should be caught there. See #136.', + DeprecationWarning, + ) + + if stop_event is None: + stop_event_: 'AnyEvent' = anyio.Event() + else: + stop_event_ = stop_event + + force_polling = _default_force_pulling(force_polling) + with RustNotify([str(p) for p in paths], debug, force_polling, poll_delay_ms) as watcher: + timeout = _calc_async_timeout(rust_timeout) + CancelledError = anyio.get_cancelled_exc_class() + + while True: + async with anyio.create_task_group() as tg: + try: + raw_changes = await anyio.to_thread.run_sync(watcher.watch, debounce, step, timeout, stop_event_) + except (CancelledError, KeyboardInterrupt): + stop_event_.set() + # suppressing KeyboardInterrupt wouldn't stop it getting raised by the top level asyncio.run call + raise + tg.cancel_scope.cancel() + + if raw_changes == 'timeout': + if yield_on_timeout: + yield set() + else: + logger.debug('rust notify timeout, continuing') + elif raw_changes == 'stop': + return + elif raw_changes == 'signal': + # in theory the watch thread should never get a signal + raise RuntimeError('watch thread unexpectedly received a signal') + else: + changes = _prep_changes(raw_changes, watch_filter) + if changes: + _log_changes(changes) + yield changes + + +def _prep_changes( + raw_changes: Set[Tuple[int, str]], watch_filter: Optional[Callable[[Change, str], bool]] +) -> Set[FileChange]: + # if we wanted to be really snazzy, we could move this into rust + changes = {(Change(change), path) for change, path in raw_changes} + if watch_filter: + changes = {c for c in changes if watch_filter(c[0], c[1])} + return changes + + +def _log_changes(changes: Set[FileChange]) -> None: + if logger.isEnabledFor(logging.INFO): # pragma: no branch + count = len(changes) + plural = '' if count == 1 else 's' + if logger.isEnabledFor(logging.DEBUG): + logger.debug('%d change%s detected: %s', count, plural, changes) + else: + logger.info('%d change%s detected', count, plural) + + +def _calc_async_timeout(timeout: Optional[int]) -> int: + """ + see https://github.com/samuelcolvin/watchfiles/issues/110 + """ + if timeout is None: + if sys.platform == 'win32': + return 1_000 + else: + return 5_000 + else: + return timeout + + +def _default_force_pulling(force_polling: Optional[bool]) -> bool: + """ + https://github.com/samuelcolvin/watchfiles/issues/167#issuecomment-1189309354 for rationale. + """ + if force_polling is None: + return 'WATCHFILES_FORCE_POLLING' in os.environ + else: + return force_polling diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/py.typed new file mode 100644 index 00000000..7cd6d6f0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. The watchfiles package uses inline types. diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/run.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/run.py new file mode 100644 index 00000000..0d0bfc2c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/run.py @@ -0,0 +1,384 @@ +import contextlib +import json +import logging +import os +import re +import shlex +import signal +import subprocess +import sys +from importlib import import_module +from multiprocessing import get_context +from multiprocessing.context import SpawnProcess +from pathlib import Path +from typing import TYPE_CHECKING, Any, Callable, Dict, Generator, Optional, Set, Tuple, Union + +import anyio + +from .filters import DefaultFilter +from .main import Change, FileChange, awatch, watch + +if TYPE_CHECKING: + try: + from typing import Literal + except ImportError: + from typing_extensions import Literal # type: ignore[misc] + +__all__ = 'run_process', 'arun_process', 'detect_target_type', 'import_string' +logger = logging.getLogger('watchfiles.main') + + +def run_process( + *paths: Union[Path, str], + target: Union[str, Callable[..., Any]], + args: Tuple[Any, ...] = (), + kwargs: Optional[Dict[str, Any]] = None, + target_type: "Literal['function', 'command', 'auto']" = 'auto', + callback: Optional[Callable[[Set[FileChange]], None]] = None, + watch_filter: Optional[Callable[[Change, str], bool]] = DefaultFilter(), + debounce: int = 1_600, + step: int = 50, + debug: bool = False, + sigint_timeout: int = 5, + sigkill_timeout: int = 1, +) -> int: + """ + Run a process and restart it upon file changes. + + `run_process` can work in two ways: + + * Using `multiprocessing.Process` † to run a python function + * Or, using `subprocess.Popen` to run a command + + !!! note + + **†** technically `multiprocessing.get_context('spawn').Process` to avoid forking and improve + code reload/import. + + Internally, `run_process` uses [`watch`][watchfiles.watch] with `raise_interrupt=False` so the function + exits cleanly upon `Ctrl+C`. + + Args: + *paths: matches the same argument of [`watch`][watchfiles.watch] + target: function or command to run + args: arguments to pass to `target`, only used if `target` is a function + kwargs: keyword arguments to pass to `target`, only used if `target` is a function + target_type: type of target. Can be `'function'`, `'command'`, or `'auto'` in which case + [`detect_target_type`][watchfiles.run.detect_target_type] is used to determine the type. + callback: function to call on each reload, the function should accept a set of changes as the sole argument + watch_filter: matches the same argument of [`watch`][watchfiles.watch] + debounce: matches the same argument of [`watch`][watchfiles.watch] + step: matches the same argument of [`watch`][watchfiles.watch] + debug: matches the same argument of [`watch`][watchfiles.watch] + sigint_timeout: the number of seconds to wait after sending sigint before sending sigkill + sigkill_timeout: the number of seconds to wait after sending sigkill before raising an exception + + Returns: + number of times the function was reloaded. + + ```py title="Example of run_process running a function" + from watchfiles import run_process + + def callback(changes): + print('changes detected:', changes) + + def foobar(a, b): + print('foobar called with:', a, b) + + if __name__ == '__main__': + run_process('./path/to/dir', target=foobar, args=(1, 2), callback=callback) + ``` + + As well as using a `callback` function, changes can be accessed from within the target function, + using the `WATCHFILES_CHANGES` environment variable. + + ```py title="Example of run_process accessing changes" + from watchfiles import run_process + + def foobar(a, b, c): + # changes will be an empty list "[]" the first time the function is called + changes = os.getenv('WATCHFILES_CHANGES') + changes = json.loads(changes) + print('foobar called due to changes:', changes) + + if __name__ == '__main__': + run_process('./path/to/dir', target=foobar, args=(1, 2, 3)) + ``` + + Again with the target as `command`, `WATCHFILES_CHANGES` can be used + to access changes. + + ```bash title="example.sh" + echo "changers: ${WATCHFILES_CHANGES}" + ``` + + ```py title="Example of run_process running a command" + from watchfiles import run_process + + if __name__ == '__main__': + run_process('.', target='./example.sh') + ``` + """ + if target_type == 'auto': + target_type = detect_target_type(target) + + logger.debug('running "%s" as %s', target, target_type) + process = start_process(target, target_type, args, kwargs) + reloads = 0 + + try: + for changes in watch( + *paths, watch_filter=watch_filter, debounce=debounce, step=step, debug=debug, raise_interrupt=False + ): + callback and callback(changes) + process.stop(sigint_timeout=sigint_timeout, sigkill_timeout=sigkill_timeout) + process = start_process(target, target_type, args, kwargs, changes) + reloads += 1 + finally: + process.stop() + return reloads + + +async def arun_process( + *paths: Union[Path, str], + target: Union[str, Callable[..., Any]], + args: Tuple[Any, ...] = (), + kwargs: Optional[Dict[str, Any]] = None, + target_type: "Literal['function', 'command', 'auto']" = 'auto', + callback: Optional[Callable[[Set[FileChange]], Any]] = None, + watch_filter: Optional[Callable[[Change, str], bool]] = DefaultFilter(), + debounce: int = 1_600, + step: int = 50, + debug: bool = False, +) -> int: + """ + Async equivalent of [`run_process`][watchfiles.run_process], all arguments match those of `run_process` except + `callback` which can be a coroutine. + + Starting and stopping the process and watching for changes is done in a separate thread. + + As with `run_process`, internally `arun_process` uses [`awatch`][watchfiles.awatch], however `KeyboardInterrupt` + cannot be caught and suppressed in `awatch` so these errors need to be caught separately, see below. + + ```py title="Example of arun_process usage" + import asyncio + from watchfiles import arun_process + + async def callback(changes): + await asyncio.sleep(0.1) + print('changes detected:', changes) + + def foobar(a, b): + print('foobar called with:', a, b) + + async def main(): + await arun_process('.', target=foobar, args=(1, 2), callback=callback) + + if __name__ == '__main__': + try: + asyncio.run(main()) + except KeyboardInterrupt: + print('stopped via KeyboardInterrupt') + ``` + """ + import inspect + + if target_type == 'auto': + target_type = detect_target_type(target) + + logger.debug('running "%s" as %s', target, target_type) + process = await anyio.to_thread.run_sync(start_process, target, target_type, args, kwargs) + reloads = 0 + + async for changes in awatch(*paths, watch_filter=watch_filter, debounce=debounce, step=step, debug=debug): + if callback is not None: + r = callback(changes) + if inspect.isawaitable(r): + await r + + await anyio.to_thread.run_sync(process.stop) + process = await anyio.to_thread.run_sync(start_process, target, target_type, args, kwargs, changes) + reloads += 1 + await anyio.to_thread.run_sync(process.stop) + return reloads + + +# Use spawn context to make sure code run in subprocess +# does not reuse imported modules in main process/context +spawn_context = get_context('spawn') + + +def start_process( + target: Union[str, Callable[..., Any]], + target_type: "Literal['function', 'command']", + args: Tuple[Any, ...], + kwargs: Optional[Dict[str, Any]], + changes: Optional[Set[FileChange]] = None, +) -> 'CombinedProcess': + if changes is None: + changes_env_var = '[]' + else: + changes_env_var = json.dumps([[c.raw_str(), p] for c, p in changes]) + + os.environ['WATCHFILES_CHANGES'] = changes_env_var + + process: 'Union[SpawnProcess, subprocess.Popen[bytes]]' + if target_type == 'function': + kwargs = kwargs or {} + if isinstance(target, str): + args = target, get_tty_path(), args, kwargs + target_ = run_function + kwargs = {} + else: + target_ = target + + process = spawn_context.Process(target=target_, args=args, kwargs=kwargs) + process.start() + else: + if args or kwargs: + logger.warning('ignoring args and kwargs for "command" target') + + assert isinstance(target, str), 'target must be a string to run as a command' + popen_args = shlex.split(target) + process = subprocess.Popen(popen_args) + return CombinedProcess(process) + + +def detect_target_type(target: Union[str, Callable[..., Any]]) -> "Literal['function', 'command']": + """ + Used by [`run_process`][watchfiles.run_process], [`arun_process`][watchfiles.arun_process] + and indirectly the CLI to determine the target type with `target_type` is `auto`. + + Detects the target type - either `function` or `command`. This method is only called with `target_type='auto'`. + + The following logic is employed: + + * If `target` is not a string, it is assumed to be a function + * If `target` ends with `.py` or `.sh`, it is assumed to be a command + * Otherwise, the target is assumed to be a function if it matches the regex `[a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+)+` + + If this logic does not work for you, specify the target type explicitly using the `target_type` function argument + or `--target-type` command line argument. + + Args: + target: The target value + + Returns: + either `'function'` or `'command'` + """ + if not isinstance(target, str): + return 'function' + elif target.endswith(('.py', '.sh')): + return 'command' + elif re.fullmatch(r'[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)+', target): + return 'function' + else: + return 'command' + + +class CombinedProcess: + def __init__(self, p: 'Union[SpawnProcess, subprocess.Popen[bytes]]'): + self._p = p + assert self.pid is not None, 'process not yet spawned' + + def stop(self, sigint_timeout: int = 5, sigkill_timeout: int = 1) -> None: + os.environ.pop('WATCHFILES_CHANGES', None) + if self.is_alive(): + logger.debug('stopping process...') + + os.kill(self.pid, signal.SIGINT) + + try: + self.join(sigint_timeout) + except subprocess.TimeoutExpired: + # Capture this exception to allow the self.exitcode to be reached. + # This will allow the SIGKILL to be sent, otherwise it is swallowed up. + logger.warning('SIGINT timed out after %r seconds', sigint_timeout) + pass + + if self.exitcode is None: + logger.warning('process has not terminated, sending SIGKILL') + os.kill(self.pid, signal.SIGKILL) + self.join(sigkill_timeout) + else: + logger.debug('process stopped') + else: + logger.warning('process already dead, exit code: %d', self.exitcode) + + def is_alive(self) -> bool: + if isinstance(self._p, SpawnProcess): + return self._p.is_alive() + else: + return self._p.poll() is None + + @property + def pid(self) -> int: + # we check the process has always been spawned when CombinedProcess is initialised + return self._p.pid # type: ignore[return-value] + + def join(self, timeout: int) -> None: + if isinstance(self._p, SpawnProcess): + self._p.join(timeout) + else: + self._p.wait(timeout) + + @property + def exitcode(self) -> Optional[int]: + if isinstance(self._p, SpawnProcess): + return self._p.exitcode + else: + return self._p.returncode + + +def run_function(function: str, tty_path: Optional[str], args: Tuple[Any, ...], kwargs: Dict[str, Any]) -> None: + with set_tty(tty_path): + func = import_string(function) + func(*args, **kwargs) + + +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. + """ + 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 get_tty_path() -> Optional[str]: # pragma: no cover + """ + Return the path to the current TTY, if any. + + Virtually impossible to test in pytest, hence no cover. + """ + try: + return os.ttyname(sys.stdin.fileno()) + except OSError: + # fileno() always fails with pytest + return '/dev/tty' + except AttributeError: + # on Windows. No idea of a better solution + return None + + +@contextlib.contextmanager +def set_tty(tty_path: Optional[str]) -> Generator[None, None, None]: + if tty_path: + try: + with open(tty_path) as tty: # pragma: no cover + sys.stdin = tty + yield + except OSError: + # eg. "No such device or address: '/dev/tty'", see https://github.com/samuelcolvin/watchfiles/issues/40 + yield + else: + # currently on windows tty_path is None and there's nothing we can do here + yield diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/version.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/version.py new file mode 100644 index 00000000..f55721f1 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/watchfiles/version.py @@ -0,0 +1,5 @@ +from ._rust_notify import __version__ + +__all__ = ('VERSION',) + +VERSION = __version__ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/LICENSE b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/LICENSE new file mode 100644 index 00000000..119b29ef --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2013-2021 Aymeric Augustin 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: + + * 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 websockets 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/METADATA new file mode 100644 index 00000000..3b042a3f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/METADATA @@ -0,0 +1,174 @@ +Metadata-Version: 2.1 +Name: websockets +Version: 10.3 +Summary: An implementation of the WebSocket Protocol (RFC 6455 & 7692) +Home-page: https://github.com/aaugustin/websockets +Author: Aymeric Augustin +Author-email: aymeric.augustin@m4x.org +License: BSD +Project-URL: Changelog, https://websockets.readthedocs.io/en/stable/project/changelog.html +Project-URL: Documentation, https://websockets.readthedocs.io/ +Project-URL: Funding, https://tidelift.com/subscription/pkg/pypi-websockets?utm_source=pypi-websockets&utm_medium=referral&utm_campaign=readme +Project-URL: Tracker, https://github.com/aaugustin/websockets/issues +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: 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 +Requires-Python: >=3.7 +License-File: LICENSE + +.. image:: logo/horizontal.svg + :width: 480px + :alt: websockets + +|licence| |version| |pyversions| |wheel| |tests| |docs| + +.. |licence| image:: https://img.shields.io/pypi/l/websockets.svg + :target: https://pypi.python.org/pypi/websockets + +.. |version| image:: https://img.shields.io/pypi/v/websockets.svg + :target: https://pypi.python.org/pypi/websockets + +.. |pyversions| image:: https://img.shields.io/pypi/pyversions/websockets.svg + :target: https://pypi.python.org/pypi/websockets + +.. |wheel| image:: https://img.shields.io/pypi/wheel/websockets.svg + :target: https://pypi.python.org/pypi/websockets + +.. |tests| image:: https://img.shields.io/github/checks-status/aaugustin/websockets/main + :target: https://github.com/aaugustin/websockets/actions/workflows/tests.yml + +.. |docs| image:: https://img.shields.io/readthedocs/websockets.svg + :target: https://websockets.readthedocs.io/ + +What is ``websockets``? +----------------------- + +websockets is a library for building WebSocket_ servers and clients in Python +with a focus on correctness, simplicity, robustness, and performance. + +.. _WebSocket: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API + +Built on top of ``asyncio``, Python's standard asynchronous I/O framework, it +provides an elegant coroutine-based API. + +`Documentation is available on Read the Docs. `_ + +Here's how a client sends and receives messages: + +.. copy-pasted because GitHub doesn't support the include directive + +.. code:: python + + #!/usr/bin/env python + + import asyncio + from websockets import connect + + async def hello(uri): + async with connect(uri) as websocket: + await websocket.send("Hello world!") + await websocket.recv() + + asyncio.run(hello("ws://localhost:8765")) + +And here's an echo server: + +.. code:: python + + #!/usr/bin/env python + + import asyncio + from websockets import serve + + async def echo(websocket): + async for message in websocket: + await websocket.send(message) + + async def main(): + async with serve(echo, "localhost", 8765): + await asyncio.Future() # run forever + + asyncio.run(main()) + +Does that look good? + +`Get started with the tutorial! `_ + +Why should I use ``websockets``? +-------------------------------- + +The development of ``websockets`` is shaped by four principles: + +1. **Correctness**: ``websockets`` is heavily tested for compliance + with :rfc:`6455`. Continuous integration fails under 100% branch + coverage. + +2. **Simplicity**: all you need to understand is ``msg = await ws.recv()`` and + ``await ws.send(msg)``. ``websockets`` takes care of managing connections + so you can focus on your application. + +3. **Robustness**: ``websockets`` is built for production. For example, it was + the only library to `handle backpressure correctly`_ before the issue + became widely known in the Python community. + +4. **Performance**: memory usage is optimized and configurable. A C extension + accelerates expensive operations. It's pre-compiled for Linux, macOS and + Windows and packaged in the wheel format for each system and Python version. + +Documentation is a first class concern in the project. Head over to `Read the +Docs`_ and see for yourself. + +.. _Read the Docs: https://websockets.readthedocs.io/ +.. _handle backpressure correctly: https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/#websocket-servers + +Why shouldn't I use ``websockets``? +----------------------------------- + +* If you prefer callbacks over coroutines: ``websockets`` was created to + provide the best coroutine-based API to manage WebSocket connections in + Python. Pick another library for a callback-based API. + +* If you're looking for a mixed HTTP / WebSocket library: ``websockets`` aims + at being an excellent implementation of :rfc:`6455`: The WebSocket Protocol + and :rfc:`7692`: Compression Extensions for WebSocket. Its support for HTTP + is minimal — just enough for a HTTP health check. + + If you want to do both in the same server, look at HTTP frameworks that + build on top of ``websockets`` to support WebSocket connections, like + Sanic_. + +.. _Sanic: https://sanicframework.org/en/ + +What else? +---------- + +Bug reports, patches and suggestions are welcome! + +To report a security vulnerability, please use the `Tidelift security +contact`_. Tidelift will coordinate the fix and disclosure. + +.. _Tidelift security contact: https://tidelift.com/security + +For anything else, please open an issue_ or send a `pull request`_. + +.. _issue: https://github.com/aaugustin/websockets/issues/new +.. _pull request: https://github.com/aaugustin/websockets/compare/ + +Participants must uphold the `Contributor Covenant code of conduct`_. + +.. _Contributor Covenant code of conduct: https://github.com/aaugustin/websockets/blob/main/CODE_OF_CONDUCT.md + +``websockets`` is released under the `BSD license`_. + +.. _BSD license: https://github.com/aaugustin/websockets/blob/main/LICENSE + + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/RECORD new file mode 100644 index 00000000..c959a8a3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/RECORD @@ -0,0 +1,68 @@ +websockets-10.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +websockets-10.3.dist-info/LICENSE,sha256=kG_hZrUJEDUNhf1QXczOB8McRhHHTRKtrzWz42bfX1A,1561 +websockets-10.3.dist-info/METADATA,sha256=WmVHPSlLRfuF4mgoL8iR6ZcWzt28qG077rtpGHsF6XU,6309 +websockets-10.3.dist-info/RECORD,, +websockets-10.3.dist-info/WHEEL,sha256=OmDKD3JmZjhMu_YdpkiJDfFL1rf8n9nexhWCGhSBGVE,101 +websockets-10.3.dist-info/top_level.txt,sha256=AmmQQqhFwjoCEKzNajXY5f28yxLP_cgVflJES82E_cs,51 +websockets/__init__.py,sha256=JjTVh9iIoob-Gjyt6gYG9AGGUACdwgRmplR4OUzuyf8,3550 +websockets/__main__.py,sha256=-7FCp_ucYi9s3JgRZ5ba23-SwTVu49Lnm1L4GKcEBcQ,7485 +websockets/__pycache__/__init__.cpython-37.pyc,, +websockets/__pycache__/__main__.cpython-37.pyc,, +websockets/__pycache__/auth.cpython-37.pyc,, +websockets/__pycache__/client.cpython-37.pyc,, +websockets/__pycache__/connection.cpython-37.pyc,, +websockets/__pycache__/datastructures.cpython-37.pyc,, +websockets/__pycache__/exceptions.cpython-37.pyc,, +websockets/__pycache__/frames.cpython-37.pyc,, +websockets/__pycache__/headers.cpython-37.pyc,, +websockets/__pycache__/http.cpython-37.pyc,, +websockets/__pycache__/http11.cpython-37.pyc,, +websockets/__pycache__/imports.cpython-37.pyc,, +websockets/__pycache__/server.cpython-37.pyc,, +websockets/__pycache__/streams.cpython-37.pyc,, +websockets/__pycache__/typing.cpython-37.pyc,, +websockets/__pycache__/uri.cpython-37.pyc,, +websockets/__pycache__/utils.cpython-37.pyc,, +websockets/__pycache__/version.cpython-37.pyc,, +websockets/auth.py,sha256=U8oQCEDDnPantIlLEYyjW3X6EtPLH3Vmw_OyapuXaQM,151 +websockets/client.py,sha256=lyPsC7I9ASv6FlFcnAMWmrRwRxWA122q1VwfAqSCL2Y,12305 +websockets/connection.py,sha256=-rhs_Mq75xfPDEJkk_vegtze9dkuqZNwBofOrya8spQ,24367 +websockets/datastructures.py,sha256=b-J8Hq-Ori5zXkrdFpV6iXh2kGFrf8m4PHKp_49zmXc,5938 +websockets/exceptions.py,sha256=lwKzfdZLmr2gRzu3P_vpQLAh6LKcPqKLg7UjxW99c3c,10447 +websockets/extensions/__init__.py,sha256=HdQaQhOVkCR5RJVRKXG5Xmb6cMpAhLaKgRikYRzO64E,102 +websockets/extensions/__pycache__/__init__.cpython-37.pyc,, +websockets/extensions/__pycache__/base.cpython-37.pyc,, +websockets/extensions/__pycache__/permessage_deflate.cpython-37.pyc,, +websockets/extensions/base.py,sha256=vbbMikoNFH8sQpsED2NYXuY_2t1CqE1waUvZQY5ZuQY,3229 +websockets/extensions/permessage_deflate.py,sha256=iuzOzLQMuzjGEAvODk9dyfYtxw7qnW6xtqgnDsCS8kM,25444 +websockets/frames.py,sha256=SNOMWoPR1e-9IYoVeFNt-II307dysVXQS1FJCF8oAXA,12824 +websockets/headers.py,sha256=ZSdzxVAcJ_O4fEg-PK3v7uuMWoOOR936TOdmt2ceg4U,16707 +websockets/http.py,sha256=yGB2GWFxQk52lRmzLWC5ks2U6Eej39n6rIYF-nff7jw,674 +websockets/http11.py,sha256=ChjoAc3A1frS8I6Ra4Jk_yt_LO7cM53z_bRmVxxmd-g,13056 +websockets/imports.py,sha256=9BnKfdMY-4RW_uRv_DkOhDs1i6ZhrWIp245QWZagajc,2889 +websockets/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +websockets/legacy/__pycache__/__init__.cpython-37.pyc,, +websockets/legacy/__pycache__/auth.cpython-37.pyc,, +websockets/legacy/__pycache__/client.cpython-37.pyc,, +websockets/legacy/__pycache__/compatibility.cpython-37.pyc,, +websockets/legacy/__pycache__/framing.cpython-37.pyc,, +websockets/legacy/__pycache__/handshake.cpython-37.pyc,, +websockets/legacy/__pycache__/http.cpython-37.pyc,, +websockets/legacy/__pycache__/protocol.cpython-37.pyc,, +websockets/legacy/__pycache__/server.cpython-37.pyc,, +websockets/legacy/auth.py,sha256=Elv_O4vxQevBakNwakbgO4o_XIPgJdVnyAU9tMPyhgU,6665 +websockets/legacy/client.py,sha256=_EKhKMoozOnN9Mh6s8x4FsBBadK8vGarhY3qwatFKy0,26718 +websockets/legacy/compatibility.py,sha256=kFh6P2833WNrCi2VrlvTRSvI5Lb1sKziLodfXY2ZX2c,327 +websockets/legacy/framing.py,sha256=caDXTke4l0wzoGtFsXSdGbBjkmR_yocC71NbkPgl1RM,5195 +websockets/legacy/handshake.py,sha256=hsMPP45ibzSkc0tQd0hKJ0HYk0TJqdq7ATyjXqTDs_g,5641 +websockets/legacy/http.py,sha256=kXKCpXKCjISBgrXWjJqTThlhEjZlPIQgCV330GoaYCM,7131 +websockets/legacy/protocol.py,sha256=-FkJB9BG_SQMB415O2fyxvV3auCWUfon2glUZ3C47-E,63434 +websockets/legacy/server.py,sha256=UK_F7K_hhaCdOGb7cdczJv1rjmqHbEOrMOl3hIAagTY,44234 +websockets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +websockets/server.py,sha256=1h2tlOrbH7DG86qUGitGmx_HhWPL0NXeR_jHBYDq0rs,19110 +websockets/speedups.cp37-win_amd64.pyd,sha256=fwaos1nrC9tZ-HmNfq-JyOb40vgLa_H7yR2ClLggjf8,11264 +websockets/streams.py,sha256=PbVlfaUjsRo70fO6zOnvae-9M3Bnh2PUu43f27WHknc,4189 +websockets/typing.py,sha256=YNw2qGqZgZTMB4kqfxincSX0xfZMT_QglvZFUXwDucs,1444 +websockets/uri.py,sha256=iG2uPx953hEm4JM1NZLrULtCcAzb6TCUe0sx3O_gecQ,3309 +websockets/utils.py,sha256=nz3tb3CXB6xtssMM2fUFDXPqHPq1XeNRFog9tAzJpPk,1201 +websockets/version.py,sha256=buwxuegDY32aazHDKEl6Fu5pNHgJKKbjmFRuPB-qXt8,2799 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/WHEEL new file mode 100644 index 00000000..54091f94 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: false +Tag: cp37-cp37m-win_amd64 + diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/top_level.txt new file mode 100644 index 00000000..5474af74 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets-10.3.dist-info/top_level.txt @@ -0,0 +1,3 @@ +websockets +websockets/extensions +websockets/legacy diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__init__.py new file mode 100644 index 00000000..ec348412 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__init__.py @@ -0,0 +1,114 @@ +from __future__ import annotations + +from .imports import lazy_import +from .version import version as __version__ # noqa + + +__all__ = [ # noqa + "AbortHandshake", + "basic_auth_protocol_factory", + "BasicAuthWebSocketServerProtocol", + "broadcast", + "ClientConnection", + "connect", + "ConnectionClosed", + "ConnectionClosedError", + "ConnectionClosedOK", + "Data", + "DuplicateParameter", + "ExtensionName", + "ExtensionParameter", + "InvalidHandshake", + "InvalidHeader", + "InvalidHeaderFormat", + "InvalidHeaderValue", + "InvalidMessage", + "InvalidOrigin", + "InvalidParameterName", + "InvalidParameterValue", + "InvalidState", + "InvalidStatus", + "InvalidStatusCode", + "InvalidUpgrade", + "InvalidURI", + "LoggerLike", + "NegotiationError", + "Origin", + "parse_uri", + "PayloadTooBig", + "ProtocolError", + "RedirectHandshake", + "SecurityError", + "serve", + "ServerConnection", + "Subprotocol", + "unix_connect", + "unix_serve", + "WebSocketClientProtocol", + "WebSocketCommonProtocol", + "WebSocketException", + "WebSocketProtocolError", + "WebSocketServer", + "WebSocketServerProtocol", + "WebSocketURI", +] + +lazy_import( + globals(), + aliases={ + "auth": ".legacy", + "basic_auth_protocol_factory": ".legacy.auth", + "BasicAuthWebSocketServerProtocol": ".legacy.auth", + "broadcast": ".legacy.protocol", + "ClientConnection": ".client", + "connect": ".legacy.client", + "unix_connect": ".legacy.client", + "WebSocketClientProtocol": ".legacy.client", + "Headers": ".datastructures", + "MultipleValuesError": ".datastructures", + "WebSocketException": ".exceptions", + "ConnectionClosed": ".exceptions", + "ConnectionClosedError": ".exceptions", + "ConnectionClosedOK": ".exceptions", + "InvalidHandshake": ".exceptions", + "SecurityError": ".exceptions", + "InvalidMessage": ".exceptions", + "InvalidHeader": ".exceptions", + "InvalidHeaderFormat": ".exceptions", + "InvalidHeaderValue": ".exceptions", + "InvalidOrigin": ".exceptions", + "InvalidUpgrade": ".exceptions", + "InvalidStatus": ".exceptions", + "InvalidStatusCode": ".exceptions", + "NegotiationError": ".exceptions", + "DuplicateParameter": ".exceptions", + "InvalidParameterName": ".exceptions", + "InvalidParameterValue": ".exceptions", + "AbortHandshake": ".exceptions", + "RedirectHandshake": ".exceptions", + "InvalidState": ".exceptions", + "InvalidURI": ".exceptions", + "PayloadTooBig": ".exceptions", + "ProtocolError": ".exceptions", + "WebSocketProtocolError": ".exceptions", + "protocol": ".legacy", + "WebSocketCommonProtocol": ".legacy.protocol", + "ServerConnection": ".server", + "serve": ".legacy.server", + "unix_serve": ".legacy.server", + "WebSocketServerProtocol": ".legacy.server", + "WebSocketServer": ".legacy.server", + "Data": ".typing", + "LoggerLike": ".typing", + "Origin": ".typing", + "ExtensionHeader": ".typing", + "ExtensionParameter": ".typing", + "Subprotocol": ".typing", + }, + deprecated_aliases={ + "framing": ".legacy", + "handshake": ".legacy", + "parse_uri": ".uri", + "WebSocketURI": ".uri", + }, +) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__main__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__main__.py new file mode 100644 index 00000000..c562d21b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/__main__.py @@ -0,0 +1,230 @@ +from __future__ import annotations + +import argparse +import asyncio +import os +import signal +import sys +import threading +from typing import Any, Set + +from .exceptions import ConnectionClosed +from .frames import Close +from .legacy.client import connect +from .version import version as websockets_version + + +if sys.platform == "win32": + + def win_enable_vt100() -> None: + """ + Enable VT-100 for console output on Windows. + + See also https://bugs.python.org/issue29059. + + """ + import ctypes + + STD_OUTPUT_HANDLE = ctypes.c_uint(-11) + INVALID_HANDLE_VALUE = ctypes.c_uint(-1) + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x004 + + handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) + if handle == INVALID_HANDLE_VALUE: + raise RuntimeError("unable to obtain stdout handle") + + cur_mode = ctypes.c_uint() + if ctypes.windll.kernel32.GetConsoleMode(handle, ctypes.byref(cur_mode)) == 0: + raise RuntimeError("unable to query current console mode") + + # ctypes ints lack support for the required bit-OR operation. + # Temporarily convert to Py int, do the OR and convert back. + py_int_mode = int.from_bytes(cur_mode, sys.byteorder) + new_mode = ctypes.c_uint(py_int_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING) + + if ctypes.windll.kernel32.SetConsoleMode(handle, new_mode) == 0: + raise RuntimeError("unable to set console mode") + + +def exit_from_event_loop_thread( + loop: asyncio.AbstractEventLoop, + stop: asyncio.Future[None], +) -> None: + loop.stop() + if not stop.done(): + # When exiting the thread that runs the event loop, raise + # KeyboardInterrupt in the main thread to exit the program. + if sys.platform == "win32": + ctrl_c = signal.CTRL_C_EVENT + else: + ctrl_c = signal.SIGINT + os.kill(os.getpid(), ctrl_c) + + +def print_during_input(string: str) -> None: + sys.stdout.write( + # Save cursor position + "\N{ESC}7" + # Add a new line + "\N{LINE FEED}" + # Move cursor up + "\N{ESC}[A" + # Insert blank line, scroll last line down + "\N{ESC}[L" + # Print string in the inserted blank line + f"{string}\N{LINE FEED}" + # Restore cursor position + "\N{ESC}8" + # Move cursor down + "\N{ESC}[B" + ) + sys.stdout.flush() + + +def print_over_input(string: str) -> None: + sys.stdout.write( + # Move cursor to beginning of line + "\N{CARRIAGE RETURN}" + # Delete current line + "\N{ESC}[K" + # Print string + f"{string}\N{LINE FEED}" + ) + sys.stdout.flush() + + +async def run_client( + uri: str, + loop: asyncio.AbstractEventLoop, + inputs: asyncio.Queue[str], + stop: asyncio.Future[None], +) -> None: + try: + websocket = await connect(uri) + except Exception as exc: + print_over_input(f"Failed to connect to {uri}: {exc}.") + exit_from_event_loop_thread(loop, stop) + return + else: + print_during_input(f"Connected to {uri}.") + + try: + while True: + incoming: asyncio.Future[Any] = asyncio.create_task(websocket.recv()) + outgoing: asyncio.Future[Any] = asyncio.create_task(inputs.get()) + done: Set[asyncio.Future[Any]] + pending: Set[asyncio.Future[Any]] + done, pending = await asyncio.wait( + [incoming, outgoing, stop], return_when=asyncio.FIRST_COMPLETED + ) + + # Cancel pending tasks to avoid leaking them. + if incoming in pending: + incoming.cancel() + if outgoing in pending: + outgoing.cancel() + + if incoming in done: + try: + message = incoming.result() + except ConnectionClosed: + break + else: + if isinstance(message, str): + print_during_input("< " + message) + else: + print_during_input("< (binary) " + message.hex()) + + if outgoing in done: + message = outgoing.result() + await websocket.send(message) + + if stop in done: + break + + finally: + await websocket.close() + assert websocket.close_code is not None and websocket.close_reason is not None + close_status = Close(websocket.close_code, websocket.close_reason) + + print_over_input(f"Connection closed: {close_status}.") + + exit_from_event_loop_thread(loop, stop) + + +def main() -> None: + # Parse command line arguments. + parser = argparse.ArgumentParser( + prog="python -m websockets", + description="Interactive WebSocket client.", + add_help=False, + ) + group = parser.add_mutually_exclusive_group() + group.add_argument("--version", action="store_true") + group.add_argument("uri", metavar="", nargs="?") + args = parser.parse_args() + + if args.version: + print(f"websockets {websockets_version}") + return + + if args.uri is None: + parser.error("the following arguments are required: ") + + # If we're on Windows, enable VT100 terminal support. + if sys.platform == "win32": + try: + win_enable_vt100() + except RuntimeError as exc: + sys.stderr.write( + f"Unable to set terminal to VT100 mode. This is only " + f"supported since Win10 anniversary update. Expect " + f"weird symbols on the terminal.\nError: {exc}\n" + ) + sys.stderr.flush() + + try: + import readline # noqa + except ImportError: # Windows has no `readline` normally + pass + + # Create an event loop that will run in a background thread. + loop = asyncio.new_event_loop() + + # Due to zealous removal of the loop parameter in the Queue constructor, + # we need a factory coroutine to run in the freshly created event loop. + async def queue_factory() -> asyncio.Queue[str]: + return asyncio.Queue() + + # Create a queue of user inputs. There's no need to limit its size. + inputs: asyncio.Queue[str] = loop.run_until_complete(queue_factory()) + + # Create a stop condition when receiving SIGINT or SIGTERM. + stop: asyncio.Future[None] = loop.create_future() + + # Schedule the task that will manage the connection. + loop.create_task(run_client(args.uri, loop, inputs, stop)) + + # Start the event loop in a background thread. + thread = threading.Thread(target=loop.run_forever) + thread.start() + + # Read from stdin in the main thread in order to receive signals. + try: + while True: + # Since there's no size limit, put_nowait is identical to put. + message = input("> ") + loop.call_soon_threadsafe(inputs.put_nowait, message) + except (KeyboardInterrupt, EOFError): # ^C, ^D + loop.call_soon_threadsafe(stop.set_result, None) + + # Wait for the event loop to terminate. + thread.join() + + # For reasons unclear, even though the loop is closed in the thread, + # it still thinks it's running here. + loop.close() + + +if __name__ == "__main__": + main() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/auth.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/auth.py new file mode 100644 index 00000000..afcb38cf --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/auth.py @@ -0,0 +1,4 @@ +from __future__ import annotations + +# See #940 for why lazy_import isn't used here for backwards compatibility. +from .legacy.auth import * # noqa diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/client.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/client.py new file mode 100644 index 00000000..df8e5342 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/client.py @@ -0,0 +1,347 @@ +from __future__ import annotations + +from typing import Generator, List, Optional, Sequence + +from .connection import CLIENT, CONNECTING, OPEN, Connection, State +from .datastructures import Headers, MultipleValuesError +from .exceptions import ( + InvalidHandshake, + InvalidHeader, + InvalidHeaderValue, + InvalidStatus, + InvalidUpgrade, + NegotiationError, +) +from .extensions import ClientExtensionFactory, Extension +from .headers import ( + build_authorization_basic, + build_extension, + build_host, + build_subprotocol, + parse_connection, + parse_extension, + parse_subprotocol, + parse_upgrade, +) +from .http import USER_AGENT +from .http11 import Request, Response +from .typing import ( + ConnectionOption, + ExtensionHeader, + LoggerLike, + Origin, + Subprotocol, + UpgradeProtocol, +) +from .uri import WebSocketURI +from .utils import accept_key, generate_key + + +# See #940 for why lazy_import isn't used here for backwards compatibility. +from .legacy.client import * # isort:skip # noqa + + +__all__ = ["ClientConnection"] + + +class ClientConnection(Connection): + """ + Sans-I/O implementation of a WebSocket client connection. + + Args: + wsuri: URI of the WebSocket server, parsed + with :func:`~websockets.uri.parse_uri`. + origin: value of the ``Origin`` header. This is useful when connecting + to a server that validates the ``Origin`` header to defend against + Cross-Site WebSocket Hijacking attacks. + extensions: list of supported extensions, in order in which they + should be tried. + subprotocols: list of supported subprotocols, in order of decreasing + preference. + state: initial state of the WebSocket connection. + max_size: maximum size of incoming messages in bytes; + :obj:`None` to disable the limit. + logger: logger for this connection; + defaults to ``logging.getLogger("websockets.client")``; + see the :doc:`logging guide <../topics/logging>` for details. + + """ + + def __init__( + self, + wsuri: WebSocketURI, + origin: Optional[Origin] = None, + extensions: Optional[Sequence[ClientExtensionFactory]] = None, + subprotocols: Optional[Sequence[Subprotocol]] = None, + state: State = CONNECTING, + max_size: Optional[int] = 2**20, + logger: Optional[LoggerLike] = None, + ): + super().__init__( + side=CLIENT, + state=state, + max_size=max_size, + logger=logger, + ) + self.wsuri = wsuri + self.origin = origin + self.available_extensions = extensions + self.available_subprotocols = subprotocols + self.key = generate_key() + + def connect(self) -> Request: # noqa: F811 + """ + Create a handshake request to open a connection. + + You must send the handshake request with :meth:`send_request`. + + You can modify it before sending it, for example to add HTTP headers. + + Returns: + Request: WebSocket handshake request event to send to the server. + + """ + headers = Headers() + + headers["Host"] = build_host( + self.wsuri.host, self.wsuri.port, self.wsuri.secure + ) + + if self.wsuri.user_info: + headers["Authorization"] = build_authorization_basic(*self.wsuri.user_info) + + if self.origin is not None: + headers["Origin"] = self.origin + + headers["Upgrade"] = "websocket" + headers["Connection"] = "Upgrade" + headers["Sec-WebSocket-Key"] = self.key + headers["Sec-WebSocket-Version"] = "13" + + if self.available_extensions is not None: + extensions_header = build_extension( + [ + (extension_factory.name, extension_factory.get_request_params()) + for extension_factory in self.available_extensions + ] + ) + headers["Sec-WebSocket-Extensions"] = extensions_header + + if self.available_subprotocols is not None: + protocol_header = build_subprotocol(self.available_subprotocols) + headers["Sec-WebSocket-Protocol"] = protocol_header + + headers["User-Agent"] = USER_AGENT + + return Request(self.wsuri.resource_name, headers) + + def process_response(self, response: Response) -> None: + """ + Check a handshake response. + + Args: + request: WebSocket handshake response received from the server. + + Raises: + InvalidHandshake: if the handshake response is invalid. + + """ + + if response.status_code != 101: + raise InvalidStatus(response) + + headers = response.headers + + connection: List[ConnectionOption] = sum( + [parse_connection(value) for value in headers.get_all("Connection")], [] + ) + + if not any(value.lower() == "upgrade" for value in connection): + raise InvalidUpgrade( + "Connection", ", ".join(connection) if connection else None + ) + + upgrade: List[UpgradeProtocol] = sum( + [parse_upgrade(value) for value in headers.get_all("Upgrade")], [] + ) + + # For compatibility with non-strict implementations, ignore case when + # checking the Upgrade header. It's supposed to be 'WebSocket'. + if not (len(upgrade) == 1 and upgrade[0].lower() == "websocket"): + raise InvalidUpgrade("Upgrade", ", ".join(upgrade) if upgrade else None) + + try: + s_w_accept = headers["Sec-WebSocket-Accept"] + except KeyError as exc: + raise InvalidHeader("Sec-WebSocket-Accept") from exc + except MultipleValuesError as exc: + raise InvalidHeader( + "Sec-WebSocket-Accept", + "more than one Sec-WebSocket-Accept header found", + ) from exc + + if s_w_accept != accept_key(self.key): + raise InvalidHeaderValue("Sec-WebSocket-Accept", s_w_accept) + + self.extensions = self.process_extensions(headers) + + self.subprotocol = self.process_subprotocol(headers) + + def process_extensions(self, headers: Headers) -> List[Extension]: + """ + Handle the Sec-WebSocket-Extensions HTTP response header. + + Check that each extension is supported, as well as its parameters. + + :rfc:`6455` leaves the rules up to the specification of each + extension. + + To provide this level of flexibility, for each extension accepted by + the server, we check for a match with each extension available in the + client configuration. If no match is found, an exception is raised. + + If several variants of the same extension are accepted by the server, + it may be configured several times, which won't make sense in general. + Extensions must implement their own requirements. For this purpose, + the list of previously accepted extensions is provided. + + Other requirements, for example related to mandatory extensions or the + order of extensions, may be implemented by overriding this method. + + Args: + headers: WebSocket handshake response headers. + + Returns: + List[Extension]: List of accepted extensions. + + Raises: + InvalidHandshake: to abort the handshake. + + """ + accepted_extensions: List[Extension] = [] + + extensions = headers.get_all("Sec-WebSocket-Extensions") + + if extensions: + + if self.available_extensions is None: + raise InvalidHandshake("no extensions supported") + + parsed_extensions: List[ExtensionHeader] = sum( + [parse_extension(header_value) for header_value in extensions], [] + ) + + for name, response_params in parsed_extensions: + + for extension_factory in self.available_extensions: + + # Skip non-matching extensions based on their name. + if extension_factory.name != name: + continue + + # Skip non-matching extensions based on their params. + try: + extension = extension_factory.process_response_params( + response_params, accepted_extensions + ) + except NegotiationError: + continue + + # Add matching extension to the final list. + accepted_extensions.append(extension) + + # Break out of the loop once we have a match. + break + + # If we didn't break from the loop, no extension in our list + # matched what the server sent. Fail the connection. + else: + raise NegotiationError( + f"Unsupported extension: " + f"name = {name}, params = {response_params}" + ) + + return accepted_extensions + + def process_subprotocol(self, headers: Headers) -> Optional[Subprotocol]: + """ + Handle the Sec-WebSocket-Protocol HTTP response header. + + If provided, check that it contains exactly one supported subprotocol. + + Args: + headers: WebSocket handshake response headers. + + Returns: + Optional[Subprotocol]: Subprotocol, if one was selected. + + """ + subprotocol: Optional[Subprotocol] = None + + subprotocols = headers.get_all("Sec-WebSocket-Protocol") + + if subprotocols: + + if self.available_subprotocols is None: + raise InvalidHandshake("no subprotocols supported") + + parsed_subprotocols: Sequence[Subprotocol] = sum( + [parse_subprotocol(header_value) for header_value in subprotocols], [] + ) + + if len(parsed_subprotocols) > 1: + subprotocols_display = ", ".join(parsed_subprotocols) + raise InvalidHandshake(f"multiple subprotocols: {subprotocols_display}") + + subprotocol = parsed_subprotocols[0] + + if subprotocol not in self.available_subprotocols: + raise NegotiationError(f"unsupported subprotocol: {subprotocol}") + + return subprotocol + + def send_request(self, request: Request) -> None: + """ + Send a handshake request to the server. + + Args: + request: WebSocket handshake request event. + + """ + if self.debug: + self.logger.debug("> GET %s HTTP/1.1", request.path) + for key, value in request.headers.raw_items(): + self.logger.debug("> %s: %s", key, value) + + self.writes.append(request.serialize()) + + def parse(self) -> Generator[None, None, None]: + if self.state is CONNECTING: + response = yield from Response.parse( + self.reader.read_line, + self.reader.read_exact, + self.reader.read_to_eof, + ) + + if self.debug: + code, phrase = response.status_code, response.reason_phrase + self.logger.debug("< HTTP/1.1 %d %s", code, phrase) + for key, value in response.headers.raw_items(): + self.logger.debug("< %s: %s", key, value) + if response.body is not None: + self.logger.debug("< [body] (%d bytes)", len(response.body)) + + try: + self.process_response(response) + except InvalidHandshake as exc: + response._exception = exc + self.handshake_exc = exc + self.parser = self.discard() + next(self.parser) # start coroutine + else: + assert self.state is CONNECTING + self.state = OPEN + finally: + self.events.append(response) + + yield from super().parse() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/connection.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/connection.py new file mode 100644 index 00000000..db8b5369 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/connection.py @@ -0,0 +1,702 @@ +from __future__ import annotations + +import enum +import logging +import uuid +from typing import Generator, List, Optional, Type, Union + +from .exceptions import ( + ConnectionClosed, + ConnectionClosedError, + ConnectionClosedOK, + InvalidState, + PayloadTooBig, + ProtocolError, +) +from .extensions import Extension +from .frames import ( + OK_CLOSE_CODES, + OP_BINARY, + OP_CLOSE, + OP_CONT, + OP_PING, + OP_PONG, + OP_TEXT, + Close, + Frame, +) +from .http11 import Request, Response +from .streams import StreamReader +from .typing import LoggerLike, Origin, Subprotocol + + +__all__ = [ + "Connection", + "Side", + "State", + "SEND_EOF", +] + +Event = Union[Request, Response, Frame] +"""Events that :meth:`~Connection.events_received` may return.""" + + +class Side(enum.IntEnum): + """A WebSocket connection is either a server or a client.""" + + SERVER, CLIENT = range(2) + + +SERVER = Side.SERVER +CLIENT = Side.CLIENT + + +class State(enum.IntEnum): + """A WebSocket connection is in one of these four states.""" + + CONNECTING, OPEN, CLOSING, CLOSED = range(4) + + +CONNECTING = State.CONNECTING +OPEN = State.OPEN +CLOSING = State.CLOSING +CLOSED = State.CLOSED + + +SEND_EOF = b"" +"""Sentinel signaling that the TCP connection must be half-closed.""" + + +class Connection: + """ + Sans-I/O implementation of a WebSocket connection. + + Args: + side: :attr:`~Side.CLIENT` or :attr:`~Side.SERVER`. + state: initial state of the WebSocket connection. + max_size: maximum size of incoming messages in bytes; + :obj:`None` to disable the limit. + logger: logger for this connection; depending on ``side``, + defaults to ``logging.getLogger("websockets.client")`` + or ``logging.getLogger("websockets.server")``; + see the :doc:`logging guide <../topics/logging>` for details. + + """ + + def __init__( + self, + side: Side, + state: State = OPEN, + max_size: Optional[int] = 2**20, + logger: Optional[LoggerLike] = None, + ) -> None: + # Unique identifier. For logs. + self.id: uuid.UUID = uuid.uuid4() + """Unique identifier of the connection. Useful in logs.""" + + # Logger or LoggerAdapter for this connection. + if logger is None: + logger = logging.getLogger(f"websockets.{side.name.lower()}") + self.logger: LoggerLike = logger + """Logger for this connection.""" + + # Track if DEBUG is enabled. Shortcut logging calls if it isn't. + self.debug = logger.isEnabledFor(logging.DEBUG) + + # Connection side. CLIENT or SERVER. + self.side = side + + # Connection state. Initially OPEN because subclasses handle CONNECTING. + self.state = state + + # Maximum size of incoming messages in bytes. + self.max_size = max_size + + # Current size of incoming message in bytes. Only set while reading a + # fragmented message i.e. a data frames with the FIN bit not set. + self.cur_size: Optional[int] = None + + # True while sending a fragmented message i.e. a data frames with the + # FIN bit not set. + self.expect_continuation_frame = False + + # WebSocket protocol parameters. + self.origin: Optional[Origin] = None + self.extensions: List[Extension] = [] + self.subprotocol: Optional[Subprotocol] = None + + # Close code and reason, set when a close frame is sent or received. + self.close_rcvd: Optional[Close] = None + self.close_sent: Optional[Close] = None + self.close_rcvd_then_sent: Optional[bool] = None + + # Track if an exception happened during the handshake. + self.handshake_exc: Optional[Exception] = None + """ + Exception to raise if the opening handshake failed. + + :obj:`None` if the opening handshake succeeded. + + """ + + # Track if send_eof() was called. + self.eof_sent = False + + # Parser state. + self.reader = StreamReader() + self.events: List[Event] = [] + self.writes: List[bytes] = [] + self.parser = self.parse() + next(self.parser) # start coroutine + self.parser_exc: Optional[Exception] = None + + @property + def state(self) -> State: + """ + WebSocket connection state. + + Defined in 4.1, 4.2, 7.1.3, and 7.1.4 of :rfc:`6455`. + + """ + return self._state + + @state.setter + def state(self, state: State) -> None: + if self.debug: + self.logger.debug("= connection is %s", state.name) + self._state = state + + @property + def close_code(self) -> Optional[int]: + """ + `WebSocket close code`_. + + .. _WebSocket close code: + https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5 + + :obj:`None` if the connection isn't closed yet. + + """ + if self.state is not CLOSED: + return None + elif self.close_rcvd is None: + return 1006 + else: + return self.close_rcvd.code + + @property + def close_reason(self) -> Optional[str]: + """ + `WebSocket close reason`_. + + .. _WebSocket close reason: + https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.6 + + :obj:`None` if the connection isn't closed yet. + + """ + if self.state is not CLOSED: + return None + elif self.close_rcvd is None: + return "" + else: + return self.close_rcvd.reason + + @property + def close_exc(self) -> ConnectionClosed: + """ + Exception to raise when trying to interact with a closed connection. + + Don't raise this exception while the connection :attr:`state` + is :attr:`~websockets.connection.State.CLOSING`; wait until + it's :attr:`~websockets.connection.State.CLOSED`. + + Indeed, the exception includes the close code and reason, which are + known only once the connection is closed. + + Raises: + AssertionError: if the connection isn't closed yet. + + """ + assert self.state is CLOSED, "connection isn't closed yet" + exc_type: Type[ConnectionClosed] + if ( + self.close_rcvd is not None + and self.close_sent is not None + and self.close_rcvd.code in OK_CLOSE_CODES + and self.close_sent.code in OK_CLOSE_CODES + ): + exc_type = ConnectionClosedOK + else: + exc_type = ConnectionClosedError + exc: ConnectionClosed = exc_type( + self.close_rcvd, + self.close_sent, + self.close_rcvd_then_sent, + ) + # Chain to the exception raised in the parser, if any. + exc.__cause__ = self.parser_exc + return exc + + # Public methods for receiving data. + + def receive_data(self, data: bytes) -> None: + """ + Receive data from the network. + + After calling this method: + + - You must call :meth:`data_to_send` and send this data to the network. + - You should call :meth:`events_received` and process resulting events. + + Raises: + EOFError: if :meth:`receive_eof` was called earlier. + + """ + self.reader.feed_data(data) + next(self.parser) + + def receive_eof(self) -> None: + """ + Receive the end of the data stream from the network. + + After calling this method: + + - You must call :meth:`data_to_send` and send this data to the network. + - You aren't expected to call :meth:`events_received`; it won't return + any new events. + + Raises: + EOFError: if :meth:`receive_eof` was called earlier. + + """ + self.reader.feed_eof() + next(self.parser) + + # Public methods for sending events. + + def send_continuation(self, data: bytes, fin: bool) -> None: + """ + Send a `Continuation frame`_. + + .. _Continuation frame: + https://datatracker.ietf.org/doc/html/rfc6455#section-5.6 + + Parameters: + data: payload containing the same kind of data + as the initial frame. + fin: FIN bit; set it to :obj:`True` if this is the last frame + of a fragmented message and to :obj:`False` otherwise. + + Raises: + ProtocolError: if a fragmented message isn't in progress. + + """ + if not self.expect_continuation_frame: + raise ProtocolError("unexpected continuation frame") + self.expect_continuation_frame = not fin + self.send_frame(Frame(OP_CONT, data, fin)) + + def send_text(self, data: bytes, fin: bool = True) -> None: + """ + Send a `Text frame`_. + + .. _Text frame: + https://datatracker.ietf.org/doc/html/rfc6455#section-5.6 + + Parameters: + data: payload containing text encoded with UTF-8. + fin: FIN bit; set it to :obj:`False` if this is the first frame of + a fragmented message. + + Raises: + ProtocolError: if a fragmented message is in progress. + + """ + if self.expect_continuation_frame: + raise ProtocolError("expected a continuation frame") + self.expect_continuation_frame = not fin + self.send_frame(Frame(OP_TEXT, data, fin)) + + def send_binary(self, data: bytes, fin: bool = True) -> None: + """ + Send a `Binary frame`_. + + .. _Binary frame: + https://datatracker.ietf.org/doc/html/rfc6455#section-5.6 + + Parameters: + data: payload containing arbitrary binary data. + fin: FIN bit; set it to :obj:`False` if this is the first frame of + a fragmented message. + + Raises: + ProtocolError: if a fragmented message is in progress. + + """ + if self.expect_continuation_frame: + raise ProtocolError("expected a continuation frame") + self.expect_continuation_frame = not fin + self.send_frame(Frame(OP_BINARY, data, fin)) + + def send_close(self, code: Optional[int] = None, reason: str = "") -> None: + """ + Send a `Close frame`_. + + .. _Close frame: + https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.1 + + Parameters: + code: close code. + reason: close reason. + + Raises: + ProtocolError: if a fragmented message is being sent, if the code + isn't valid, or if a reason is provided without a code + + """ + if self.expect_continuation_frame: + raise ProtocolError("expected a continuation frame") + if code is None: + if reason != "": + raise ProtocolError("cannot send a reason without a code") + close = Close(1005, "") + data = b"" + else: + close = Close(code, reason) + data = close.serialize() + # send_frame() guarantees that self.state is OPEN at this point. + # 7.1.3. The WebSocket Closing Handshake is Started + self.send_frame(Frame(OP_CLOSE, data)) + self.close_sent = close + self.state = CLOSING + + def send_ping(self, data: bytes) -> None: + """ + Send a `Ping frame`_. + + .. _Ping frame: + https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2 + + Parameters: + data: payload containing arbitrary binary data. + + """ + self.send_frame(Frame(OP_PING, data)) + + def send_pong(self, data: bytes) -> None: + """ + Send a `Pong frame`_. + + .. _Pong frame: + https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.3 + + Parameters: + data: payload containing arbitrary binary data. + + """ + self.send_frame(Frame(OP_PONG, data)) + + def fail(self, code: int, reason: str = "") -> None: + """ + `Fail the WebSocket connection`_. + + .. _Fail the WebSocket connection: + https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.7 + + Parameters: + code: close code + reason: close reason + + Raises: + ProtocolError: if the code isn't valid. + """ + # 7.1.7. Fail the WebSocket Connection + + # Send a close frame when the state is OPEN (a close frame was already + # sent if it's CLOSING), except when failing the connection because + # of an error reading from or writing to the network. + if self.state is OPEN: + if code != 1006: + close = Close(code, reason) + data = close.serialize() + self.send_frame(Frame(OP_CLOSE, data)) + self.close_sent = close + self.state = CLOSING + + # When failing the connection, a server closes the TCP connection + # without waiting for the client to complete the handshake, while a + # client waits for the server to close the TCP connection, possibly + # after sending a close frame that the client will ignore. + if self.side is SERVER and not self.eof_sent: + self.send_eof() + + # 7.1.7. Fail the WebSocket Connection "An endpoint MUST NOT continue + # to attempt to process data(including a responding Close frame) from + # the remote endpoint after being instructed to _Fail the WebSocket + # Connection_." + self.parser = self.discard() + next(self.parser) # start coroutine + + # Public method for getting incoming events after receiving data. + + def events_received(self) -> List[Event]: + """ + Fetch events generated from data received from the network. + + Call this method immediately after any of the ``receive_*()`` methods. + + Process resulting events, likely by passing them to the application. + + Returns: + List[Event]: Events read from the connection. + """ + events, self.events = self.events, [] + return events + + # Public method for getting outgoing data after receiving data or sending events. + + def data_to_send(self) -> List[bytes]: + """ + Obtain data to send to the network. + + Call this method immediately after any of the ``receive_*()``, + ``send_*()``, or :meth:`fail` methods. + + Write resulting data to the connection. + + The empty bytestring :data:`~websockets.connection.SEND_EOF` signals + the end of the data stream. When you receive it, half-close the TCP + connection. + + Returns: + List[bytes]: Data to write to the connection. + + """ + writes, self.writes = self.writes, [] + return writes + + def close_expected(self) -> bool: + """ + Tell if the TCP connection is expected to close soon. + + Call this method immediately after any of the ``receive_*()`` or + :meth:`fail` methods. + + If it returns :obj:`True`, schedule closing the TCP connection after a + short timeout if the other side hasn't already closed it. + + Returns: + bool: Whether the TCP connection is expected to close soon. + + """ + # We expect a TCP close if and only if we sent a close frame: + # * Normal closure: once we send a close frame, we expect a TCP close: + # server waits for client to complete the TCP closing handshake; + # client waits for server to initiate the TCP closing handshake. + # * Abnormal closure: we always send a close frame and the same logic + # applies, except on EOFError where we don't send a close frame + # because we already received the TCP close, so we don't expect it. + # We already got a TCP Close if and only if the state is CLOSED. + return self.state is CLOSING or self.handshake_exc is not None + + # Private methods for receiving data. + + def parse(self) -> Generator[None, None, None]: + """ + Parse incoming data into frames. + + :meth:`receive_data` and :meth:`receive_eof` run this generator + coroutine until it needs more data or reaches EOF. + + """ + try: + while True: + if (yield from self.reader.at_eof()): + if self.debug: + self.logger.debug("< EOF") + # If the WebSocket connection is closed cleanly, with a + # closing handhshake, recv_frame() substitutes parse() + # with discard(). This branch is reached only when the + # connection isn't closed cleanly. + raise EOFError("unexpected end of stream") + + if self.max_size is None: + max_size = None + elif self.cur_size is None: + max_size = self.max_size + else: + max_size = self.max_size - self.cur_size + + # During a normal closure, execution ends here on the next + # iteration of the loop after receiving a close frame. At + # this point, recv_frame() replaced parse() by discard(). + frame = yield from Frame.parse( + self.reader.read_exact, + mask=self.side is SERVER, + max_size=max_size, + extensions=self.extensions, + ) + + if self.debug: + self.logger.debug("< %s", frame) + + self.recv_frame(frame) + + except ProtocolError as exc: + self.fail(1002, str(exc)) + self.parser_exc = exc + + except EOFError as exc: + self.fail(1006, str(exc)) + self.parser_exc = exc + + except UnicodeDecodeError as exc: + self.fail(1007, f"{exc.reason} at position {exc.start}") + self.parser_exc = exc + + except PayloadTooBig as exc: + self.fail(1009, str(exc)) + self.parser_exc = exc + + except Exception as exc: + self.logger.error("parser failed", exc_info=True) + # Don't include exception details, which may be security-sensitive. + self.fail(1011) + self.parser_exc = exc + + # During an abnormal closure, execution ends here after catching an + # exception. At this point, fail() replaced parse() by discard(). + yield + raise AssertionError("parse() shouldn't step after error") # pragma: no cover + + def discard(self) -> Generator[None, None, None]: + """ + Discard incoming data. + + This coroutine replaces :meth:`parse`: + + - after receiving a close frame, during a normal closure (1.4); + - after sending a close frame, during an abnormal closure (7.1.7). + + """ + # The server close the TCP connection in the same circumstances where + # discard() replaces parse(). The client closes the connection later, + # after the server closes the connection or a timeout elapses. + # (The latter case cannot be handled in this Sans-I/O layer.) + assert (self.side is SERVER) == (self.eof_sent) + while not (yield from self.reader.at_eof()): + self.reader.discard() + if self.debug: + self.logger.debug("< EOF") + # A server closes the TCP connection immediately, while a client + # waits for the server to close the TCP connection. + if self.side is CLIENT: + self.send_eof() + self.state = CLOSED + # If discard() completes normally, execution ends here. + yield + # Once the reader reaches EOF, its feed_data/eof() methods raise an + # error, so our receive_data/eof() methods don't step the generator. + raise AssertionError("discard() shouldn't step after EOF") # pragma: no cover + + def recv_frame(self, frame: Frame) -> None: + """ + Process an incoming frame. + + """ + if frame.opcode is OP_TEXT or frame.opcode is OP_BINARY: + if self.cur_size is not None: + raise ProtocolError("expected a continuation frame") + if frame.fin: + self.cur_size = None + else: + self.cur_size = len(frame.data) + + elif frame.opcode is OP_CONT: + if self.cur_size is None: + raise ProtocolError("unexpected continuation frame") + if frame.fin: + self.cur_size = None + else: + self.cur_size += len(frame.data) + + elif frame.opcode is OP_PING: + # 5.5.2. Ping: "Upon receipt of a Ping frame, an endpoint MUST + # send a Pong frame in response" + pong_frame = Frame(OP_PONG, frame.data) + self.send_frame(pong_frame) + + elif frame.opcode is OP_PONG: + # 5.5.3 Pong: "A response to an unsolicited Pong frame is not + # expected." + pass + + elif frame.opcode is OP_CLOSE: + # 7.1.5. The WebSocket Connection Close Code + # 7.1.6. The WebSocket Connection Close Reason + self.close_rcvd = Close.parse(frame.data) + if self.state is CLOSING: + assert self.close_sent is not None + self.close_rcvd_then_sent = False + + if self.cur_size is not None: + raise ProtocolError("incomplete fragmented message") + + # 5.5.1 Close: "If an endpoint receives a Close frame and did + # not previously send a Close frame, the endpoint MUST send a + # Close frame in response. (When sending a Close frame in + # response, the endpoint typically echos the status code it + # received.)" + + if self.state is OPEN: + # Echo the original data instead of re-serializing it with + # Close.serialize() because that fails when the close frame + # is empty and Close.parse() synthetizes a 1005 close code. + # The rest is identical to send_close(). + self.send_frame(Frame(OP_CLOSE, frame.data)) + self.close_sent = self.close_rcvd + self.close_rcvd_then_sent = True + self.state = CLOSING + + # 7.1.2. Start the WebSocket Closing Handshake: "Once an + # endpoint has both sent and received a Close control frame, + # that endpoint SHOULD _Close the WebSocket Connection_" + + # A server closes the TCP connection immediately, while a client + # waits for the server to close the TCP connection. + if self.side is SERVER: + self.send_eof() + + # 1.4. Closing Handshake: "after receiving a control frame + # indicating the connection should be closed, a peer discards + # any further data received." + self.parser = self.discard() + next(self.parser) # start coroutine + + else: # pragma: no cover + # This can't happen because Frame.parse() validates opcodes. + raise AssertionError(f"unexpected opcode: {frame.opcode:02x}") + + self.events.append(frame) + + # Private methods for sending events. + + def send_frame(self, frame: Frame) -> None: + if self.state is not OPEN: + raise InvalidState( + f"cannot write to a WebSocket in the {self.state.name} state" + ) + + if self.debug: + self.logger.debug("> %s", frame) + self.writes.append( + frame.serialize(mask=self.side is CLIENT, extensions=self.extensions) + ) + + def send_eof(self) -> None: + assert not self.eof_sent + self.eof_sent = True + if self.debug: + self.logger.debug("> EOF") + self.writes.append(SEND_EOF) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/datastructures.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/datastructures.py new file mode 100644 index 00000000..36a2cbaf --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/datastructures.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +import sys +from typing import ( + Any, + Dict, + Iterable, + Iterator, + List, + Mapping, + MutableMapping, + Tuple, + Union, +) + + +if sys.version_info[:2] >= (3, 8): + from typing import Protocol +else: # pragma: no cover + Protocol = object # mypy will report errors on Python 3.7. + + +__all__ = ["Headers", "HeadersLike", "MultipleValuesError"] + + +class MultipleValuesError(LookupError): + """ + Exception raised when :class:`Headers` has more than one value for a key. + + """ + + def __str__(self) -> str: + # Implement the same logic as KeyError_str in Objects/exceptions.c. + if len(self.args) == 1: + return repr(self.args[0]) + return super().__str__() + + +class Headers(MutableMapping[str, str]): + """ + Efficient data structure for manipulating HTTP headers. + + A :class:`list` of ``(name, values)`` is inefficient for lookups. + + A :class:`dict` doesn't suffice because header names are case-insensitive + and multiple occurrences of headers with the same name are possible. + + :class:`Headers` stores HTTP headers in a hybrid data structure to provide + efficient insertions and lookups while preserving the original data. + + In order to account for multiple values with minimal hassle, + :class:`Headers` follows this logic: + + - When getting a header with ``headers[name]``: + - if there's no value, :exc:`KeyError` is raised; + - if there's exactly one value, it's returned; + - if there's more than one value, :exc:`MultipleValuesError` is raised. + + - When setting a header with ``headers[name] = value``, the value is + appended to the list of values for that header. + + - When deleting a header with ``del headers[name]``, all values for that + header are removed (this is slow). + + Other methods for manipulating headers are consistent with this logic. + + As long as no header occurs multiple times, :class:`Headers` behaves like + :class:`dict`, except keys are lower-cased to provide case-insensitivity. + + Two methods support manipulating multiple values explicitly: + + - :meth:`get_all` returns a list of all values for a header; + - :meth:`raw_items` returns an iterator of ``(name, values)`` pairs. + + """ + + __slots__ = ["_dict", "_list"] + + # Like dict, Headers accepts an optional "mapping or iterable" argument. + def __init__(self, *args: HeadersLike, **kwargs: str) -> None: + self._dict: Dict[str, List[str]] = {} + self._list: List[Tuple[str, str]] = [] + self.update(*args, **kwargs) + + def __str__(self) -> str: + return "".join(f"{key}: {value}\r\n" for key, value in self._list) + "\r\n" + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self._list!r})" + + def copy(self) -> Headers: + copy = self.__class__() + copy._dict = self._dict.copy() + copy._list = self._list.copy() + return copy + + def serialize(self) -> bytes: + # Since headers only contain ASCII characters, we can keep this simple. + return str(self).encode() + + # Collection methods + + def __contains__(self, key: object) -> bool: + return isinstance(key, str) and key.lower() in self._dict + + def __iter__(self) -> Iterator[str]: + return iter(self._dict) + + def __len__(self) -> int: + return len(self._dict) + + # MutableMapping methods + + def __getitem__(self, key: str) -> str: + value = self._dict[key.lower()] + if len(value) == 1: + return value[0] + else: + raise MultipleValuesError(key) + + def __setitem__(self, key: str, value: str) -> None: + self._dict.setdefault(key.lower(), []).append(value) + self._list.append((key, value)) + + def __delitem__(self, key: str) -> None: + key_lower = key.lower() + self._dict.__delitem__(key_lower) + # This is inefficient. Fortunately deleting HTTP headers is uncommon. + self._list = [(k, v) for k, v in self._list if k.lower() != key_lower] + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Headers): + return NotImplemented + return self._dict == other._dict + + def clear(self) -> None: + """ + Remove all headers. + + """ + self._dict = {} + self._list = [] + + def update(self, *args: HeadersLike, **kwargs: str) -> None: + """ + Update from a :class:`Headers` instance and/or keyword arguments. + + """ + args = tuple( + arg.raw_items() if isinstance(arg, Headers) else arg for arg in args + ) + super().update(*args, **kwargs) + + # Methods for handling multiple values + + def get_all(self, key: str) -> List[str]: + """ + Return the (possibly empty) list of all values for a header. + + Args: + key: header name. + + """ + return self._dict.get(key.lower(), []) + + def raw_items(self) -> Iterator[Tuple[str, str]]: + """ + Return an iterator of all values as ``(name, value)`` pairs. + + """ + return iter(self._list) + + +# copy of _typeshed.SupportsKeysAndGetItem. +class SupportsKeysAndGetItem(Protocol): # pragma: no cover + """ + Dict-like types with ``keys() -> str`` and ``__getitem__(key: str) -> str`` methods. + + """ + + def keys(self) -> Iterable[str]: + ... + + def __getitem__(self, key: str) -> str: + ... + + +HeadersLike = Union[ + Headers, + Mapping[str, str], + Iterable[Tuple[str, str]], + SupportsKeysAndGetItem, +] +""" +Types accepted where :class:`Headers` is expected. + +In addition to :class:`Headers` itself, this includes dict-like types where both +keys and values are :class:`str`. + +""" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/exceptions.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/exceptions.py new file mode 100644 index 00000000..0c4fc518 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/exceptions.py @@ -0,0 +1,398 @@ +""" +:mod:`websockets.exceptions` defines the following exception hierarchy: + +* :exc:`WebSocketException` + * :exc:`ConnectionClosed` + * :exc:`ConnectionClosedError` + * :exc:`ConnectionClosedOK` + * :exc:`InvalidHandshake` + * :exc:`SecurityError` + * :exc:`InvalidMessage` + * :exc:`InvalidHeader` + * :exc:`InvalidHeaderFormat` + * :exc:`InvalidHeaderValue` + * :exc:`InvalidOrigin` + * :exc:`InvalidUpgrade` + * :exc:`InvalidStatus` + * :exc:`InvalidStatusCode` (legacy) + * :exc:`NegotiationError` + * :exc:`DuplicateParameter` + * :exc:`InvalidParameterName` + * :exc:`InvalidParameterValue` + * :exc:`AbortHandshake` + * :exc:`RedirectHandshake` + * :exc:`InvalidState` + * :exc:`InvalidURI` + * :exc:`PayloadTooBig` + * :exc:`ProtocolError` + +""" + +from __future__ import annotations + +import http +from typing import Optional + +from . import datastructures, frames, http11 + + +__all__ = [ + "WebSocketException", + "ConnectionClosed", + "ConnectionClosedError", + "ConnectionClosedOK", + "InvalidHandshake", + "SecurityError", + "InvalidMessage", + "InvalidHeader", + "InvalidHeaderFormat", + "InvalidHeaderValue", + "InvalidOrigin", + "InvalidUpgrade", + "InvalidStatus", + "InvalidStatusCode", + "NegotiationError", + "DuplicateParameter", + "InvalidParameterName", + "InvalidParameterValue", + "AbortHandshake", + "RedirectHandshake", + "InvalidState", + "InvalidURI", + "PayloadTooBig", + "ProtocolError", + "WebSocketProtocolError", +] + + +class WebSocketException(Exception): + """ + Base class for all exceptions defined by websockets. + + """ + + +class ConnectionClosed(WebSocketException): + """ + Raised when trying to interact with a closed connection. + + Attributes: + rcvd (Optional[Close]): if a close frame was received, its code and + reason are available in ``rcvd.code`` and ``rcvd.reason``. + sent (Optional[Close]): if a close frame was sent, its code and reason + are available in ``sent.code`` and ``sent.reason``. + rcvd_then_sent (Optional[bool]): if close frames were received and + sent, this attribute tells in which order this happened, from the + perspective of this side of the connection. + + """ + + def __init__( + self, + rcvd: Optional[frames.Close], + sent: Optional[frames.Close], + rcvd_then_sent: Optional[bool] = None, + ) -> None: + self.rcvd = rcvd + self.sent = sent + self.rcvd_then_sent = rcvd_then_sent + + def __str__(self) -> str: + if self.rcvd is None: + if self.sent is None: + assert self.rcvd_then_sent is None + return "no close frame received or sent" + else: + assert self.rcvd_then_sent is None + return f"sent {self.sent}; no close frame received" + else: + if self.sent is None: + assert self.rcvd_then_sent is None + return f"received {self.rcvd}; no close frame sent" + else: + assert self.rcvd_then_sent is not None + if self.rcvd_then_sent: + return f"received {self.rcvd}; then sent {self.sent}" + else: + return f"sent {self.sent}; then received {self.rcvd}" + + # code and reason attributes are provided for backwards-compatibility + + @property + def code(self) -> int: + return 1006 if self.rcvd is None else self.rcvd.code + + @property + def reason(self) -> str: + return "" if self.rcvd is None else self.rcvd.reason + + +class ConnectionClosedError(ConnectionClosed): + """ + Like :exc:`ConnectionClosed`, when the connection terminated with an error. + + A close code other than 1000 (OK) or 1001 (going away) was received or + sent, or the closing handshake didn't complete properly. + + """ + + +class ConnectionClosedOK(ConnectionClosed): + """ + Like :exc:`ConnectionClosed`, when the connection terminated properly. + + A close code 1000 (OK) or 1001 (going away) was received and sent. + + """ + + +class InvalidHandshake(WebSocketException): + """ + Raised during the handshake when the WebSocket connection fails. + + """ + + +class SecurityError(InvalidHandshake): + """ + Raised when a handshake request or response breaks a security rule. + + Security limits are hard coded. + + """ + + +class InvalidMessage(InvalidHandshake): + """ + Raised when a handshake request or response is malformed. + + """ + + +class InvalidHeader(InvalidHandshake): + """ + Raised when a HTTP header doesn't have a valid format or value. + + """ + + def __init__(self, name: str, value: Optional[str] = None) -> None: + self.name = name + self.value = value + + def __str__(self) -> str: + if self.value is None: + return f"missing {self.name} header" + elif self.value == "": + return f"empty {self.name} header" + else: + return f"invalid {self.name} header: {self.value}" + + +class InvalidHeaderFormat(InvalidHeader): + """ + Raised when a HTTP header cannot be parsed. + + The format of the header doesn't match the grammar for that header. + + """ + + def __init__(self, name: str, error: str, header: str, pos: int) -> None: + super().__init__(name, f"{error} at {pos} in {header}") + + +class InvalidHeaderValue(InvalidHeader): + """ + Raised when a HTTP header has a wrong value. + + The format of the header is correct but a value isn't acceptable. + + """ + + +class InvalidOrigin(InvalidHeader): + """ + Raised when the Origin header in a request isn't allowed. + + """ + + def __init__(self, origin: Optional[str]) -> None: + super().__init__("Origin", origin) + + +class InvalidUpgrade(InvalidHeader): + """ + Raised when the Upgrade or Connection header isn't correct. + + """ + + +class InvalidStatus(InvalidHandshake): + """ + Raised when a handshake response rejects the WebSocket upgrade. + + """ + + def __init__(self, response: http11.Response) -> None: + self.response = response + + def __str__(self) -> str: + return ( + "server rejected WebSocket connection: " + f"HTTP {self.response.status_code:d}" + ) + + +class InvalidStatusCode(InvalidHandshake): + """ + Raised when a handshake response status code is invalid. + + """ + + def __init__(self, status_code: int, headers: datastructures.Headers) -> None: + self.status_code = status_code + self.headers = headers + + def __str__(self) -> str: + return f"server rejected WebSocket connection: HTTP {self.status_code}" + + +class NegotiationError(InvalidHandshake): + """ + Raised when negotiating an extension fails. + + """ + + +class DuplicateParameter(NegotiationError): + """ + Raised when a parameter name is repeated in an extension header. + + """ + + def __init__(self, name: str) -> None: + self.name = name + + def __str__(self) -> str: + return f"duplicate parameter: {self.name}" + + +class InvalidParameterName(NegotiationError): + """ + Raised when a parameter name in an extension header is invalid. + + """ + + def __init__(self, name: str) -> None: + self.name = name + + def __str__(self) -> str: + return f"invalid parameter name: {self.name}" + + +class InvalidParameterValue(NegotiationError): + """ + Raised when a parameter value in an extension header is invalid. + + """ + + def __init__(self, name: str, value: Optional[str]) -> None: + self.name = name + self.value = value + + def __str__(self) -> str: + if self.value is None: + return f"missing value for parameter {self.name}" + elif self.value == "": + return f"empty value for parameter {self.name}" + else: + return f"invalid value for parameter {self.name}: {self.value}" + + +class AbortHandshake(InvalidHandshake): + """ + Raised to abort the handshake on purpose and return a HTTP response. + + This exception is an implementation detail. + + The public API + is :meth:`~websockets.server.WebSocketServerProtocol.process_request`. + + Attributes: + status (~http.HTTPStatus): HTTP status code. + headers (Headers): HTTP response headers. + body (bytes): HTTP response body. + """ + + def __init__( + self, + status: http.HTTPStatus, + headers: datastructures.HeadersLike, + body: bytes = b"", + ) -> None: + self.status = status + self.headers = datastructures.Headers(headers) + self.body = body + + def __str__(self) -> str: + return ( + f"HTTP {self.status:d}, " + f"{len(self.headers)} headers, " + f"{len(self.body)} bytes" + ) + + +class RedirectHandshake(InvalidHandshake): + """ + Raised when a handshake gets redirected. + + This exception is an implementation detail. + + """ + + def __init__(self, uri: str) -> None: + self.uri = uri + + def __str__(self) -> str: + return f"redirect to {self.uri}" + + +class InvalidState(WebSocketException, AssertionError): + """ + Raised when an operation is forbidden in the current state. + + This exception is an implementation detail. + + It should never be raised in normal circumstances. + + """ + + +class InvalidURI(WebSocketException): + """ + Raised when connecting to an URI that isn't a valid WebSocket URI. + + """ + + def __init__(self, uri: str, msg: str) -> None: + self.uri = uri + self.msg = msg + + def __str__(self) -> str: + return f"{self.uri} isn't a valid URI: {self.msg}" + + +class PayloadTooBig(WebSocketException): + """ + Raised when receiving a frame with a payload exceeding the maximum size. + + """ + + +class ProtocolError(WebSocketException): + """ + Raised when a frame breaks the protocol. + + """ + + +WebSocketProtocolError = ProtocolError # for backwards compatibility diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/__init__.py new file mode 100644 index 00000000..02838b98 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/__init__.py @@ -0,0 +1,4 @@ +from .base import * + + +__all__ = ["Extension", "ClientExtensionFactory", "ServerExtensionFactory"] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/base.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/base.py new file mode 100644 index 00000000..06096761 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/base.py @@ -0,0 +1,128 @@ +from __future__ import annotations + +from typing import List, Optional, Sequence, Tuple + +from .. import frames +from ..typing import ExtensionName, ExtensionParameter + + +__all__ = ["Extension", "ClientExtensionFactory", "ServerExtensionFactory"] + + +class Extension: + """ + Base class for extensions. + + """ + + name: ExtensionName + """Extension identifier.""" + + def decode( + self, + frame: frames.Frame, + *, + max_size: Optional[int] = None, + ) -> frames.Frame: + """ + Decode an incoming frame. + + Args: + frame (Frame): incoming frame. + max_size: maximum payload size in bytes. + + Returns: + Frame: Decoded frame. + + Raises: + PayloadTooBig: if decoding the payload exceeds ``max_size``. + + """ + + def encode(self, frame: frames.Frame) -> frames.Frame: + """ + Encode an outgoing frame. + + Args: + frame (Frame): outgoing frame. + + Returns: + Frame: Encoded frame. + + """ + + +class ClientExtensionFactory: + """ + Base class for client-side extension factories. + + """ + + name: ExtensionName + """Extension identifier.""" + + def get_request_params(self) -> List[ExtensionParameter]: + """ + Build parameters to send to the server for this extension. + + Returns: + List[ExtensionParameter]: Parameters to send to the server. + + """ + + def process_response_params( + self, + params: Sequence[ExtensionParameter], + accepted_extensions: Sequence[Extension], + ) -> Extension: + """ + Process parameters received from the server. + + Args: + params (Sequence[ExtensionParameter]): parameters received from + the server for this extension. + accepted_extensions (Sequence[Extension]): list of previously + accepted extensions. + + Returns: + Extension: An extension instance. + + Raises: + NegotiationError: if parameters aren't acceptable. + + """ + + +class ServerExtensionFactory: + """ + Base class for server-side extension factories. + + """ + + name: ExtensionName + """Extension identifier.""" + + def process_request_params( + self, + params: Sequence[ExtensionParameter], + accepted_extensions: Sequence[Extension], + ) -> Tuple[List[ExtensionParameter], Extension]: + """ + Process parameters received from the client. + + Args: + params (Sequence[ExtensionParameter]): parameters received from + the client for this extension. + accepted_extensions (Sequence[Extension]): list of previously + accepted extensions. + + Returns: + Tuple[List[ExtensionParameter], Extension]: To accept the offer, + parameters to send to the client for this extension and an + extension instance. + + Raises: + NegotiationError: to reject the offer, if parameters received from + the client aren't acceptable. + + """ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/permessage_deflate.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/permessage_deflate.py new file mode 100644 index 00000000..e0de5e8f --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/extensions/permessage_deflate.py @@ -0,0 +1,661 @@ +from __future__ import annotations + +import dataclasses +import zlib +from typing import Any, Dict, List, Optional, Sequence, Tuple, Union + +from .. import exceptions, frames +from ..typing import ExtensionName, ExtensionParameter +from .base import ClientExtensionFactory, Extension, ServerExtensionFactory + + +__all__ = [ + "PerMessageDeflate", + "ClientPerMessageDeflateFactory", + "enable_client_permessage_deflate", + "ServerPerMessageDeflateFactory", + "enable_server_permessage_deflate", +] + +_EMPTY_UNCOMPRESSED_BLOCK = b"\x00\x00\xff\xff" + +_MAX_WINDOW_BITS_VALUES = [str(bits) for bits in range(8, 16)] + + +class PerMessageDeflate(Extension): + """ + Per-Message Deflate extension. + + """ + + name = ExtensionName("permessage-deflate") + + def __init__( + self, + remote_no_context_takeover: bool, + local_no_context_takeover: bool, + remote_max_window_bits: int, + local_max_window_bits: int, + compress_settings: Optional[Dict[Any, Any]] = None, + ) -> None: + """ + Configure the Per-Message Deflate extension. + + """ + if compress_settings is None: + compress_settings = {} + + assert remote_no_context_takeover in [False, True] + assert local_no_context_takeover in [False, True] + assert 8 <= remote_max_window_bits <= 15 + assert 8 <= local_max_window_bits <= 15 + assert "wbits" not in compress_settings + + self.remote_no_context_takeover = remote_no_context_takeover + self.local_no_context_takeover = local_no_context_takeover + self.remote_max_window_bits = remote_max_window_bits + self.local_max_window_bits = local_max_window_bits + self.compress_settings = compress_settings + + if not self.remote_no_context_takeover: + self.decoder = zlib.decompressobj(wbits=-self.remote_max_window_bits) + + if not self.local_no_context_takeover: + self.encoder = zlib.compressobj( + wbits=-self.local_max_window_bits, **self.compress_settings + ) + + # To handle continuation frames properly, we must keep track of + # whether that initial frame was encoded. + self.decode_cont_data = False + # There's no need for self.encode_cont_data because we always encode + # outgoing frames, so it would always be True. + + def __repr__(self) -> str: + return ( + f"PerMessageDeflate(" + f"remote_no_context_takeover={self.remote_no_context_takeover}, " + f"local_no_context_takeover={self.local_no_context_takeover}, " + f"remote_max_window_bits={self.remote_max_window_bits}, " + f"local_max_window_bits={self.local_max_window_bits})" + ) + + def decode( + self, + frame: frames.Frame, + *, + max_size: Optional[int] = None, + ) -> frames.Frame: + """ + Decode an incoming frame. + + """ + # Skip control frames. + if frame.opcode in frames.CTRL_OPCODES: + return frame + + # Handle continuation data frames: + # - skip if the message isn't encoded + # - reset "decode continuation data" flag if it's a final frame + if frame.opcode is frames.OP_CONT: + if not self.decode_cont_data: + return frame + if frame.fin: + self.decode_cont_data = False + + # Handle text and binary data frames: + # - skip if the message isn't encoded + # - unset the rsv1 flag on the first frame of a compressed message + # - set "decode continuation data" flag if it's a non-final frame + else: + if not frame.rsv1: + return frame + frame = dataclasses.replace(frame, rsv1=False) + if not frame.fin: + self.decode_cont_data = True + + # Re-initialize per-message decoder. + if self.remote_no_context_takeover: + self.decoder = zlib.decompressobj(wbits=-self.remote_max_window_bits) + + # Uncompress data. Protect against zip bombs by preventing zlib from + # decompressing more than max_length bytes (except when the limit is + # disabled with max_size = None). + data = frame.data + if frame.fin: + data += _EMPTY_UNCOMPRESSED_BLOCK + max_length = 0 if max_size is None else max_size + try: + data = self.decoder.decompress(data, max_length) + except zlib.error as exc: + raise exceptions.ProtocolError("decompression failed") from exc + if self.decoder.unconsumed_tail: + raise exceptions.PayloadTooBig(f"over size limit (? > {max_size} bytes)") + + # Allow garbage collection of the decoder if it won't be reused. + if frame.fin and self.remote_no_context_takeover: + del self.decoder + + return dataclasses.replace(frame, data=data) + + def encode(self, frame: frames.Frame) -> frames.Frame: + """ + Encode an outgoing frame. + + """ + # Skip control frames. + if frame.opcode in frames.CTRL_OPCODES: + return frame + + # Since we always encode messages, there's no "encode continuation + # data" flag similar to "decode continuation data" at this time. + + if frame.opcode is not frames.OP_CONT: + # Set the rsv1 flag on the first frame of a compressed message. + frame = dataclasses.replace(frame, rsv1=True) + # Re-initialize per-message decoder. + if self.local_no_context_takeover: + self.encoder = zlib.compressobj( + wbits=-self.local_max_window_bits, **self.compress_settings + ) + + # Compress data. + data = self.encoder.compress(frame.data) + self.encoder.flush(zlib.Z_SYNC_FLUSH) + if frame.fin and data.endswith(_EMPTY_UNCOMPRESSED_BLOCK): + data = data[:-4] + + # Allow garbage collection of the encoder if it won't be reused. + if frame.fin and self.local_no_context_takeover: + del self.encoder + + return dataclasses.replace(frame, data=data) + + +def _build_parameters( + server_no_context_takeover: bool, + client_no_context_takeover: bool, + server_max_window_bits: Optional[int], + client_max_window_bits: Optional[Union[int, bool]], +) -> List[ExtensionParameter]: + """ + Build a list of ``(name, value)`` pairs for some compression parameters. + + """ + params: List[ExtensionParameter] = [] + if server_no_context_takeover: + params.append(("server_no_context_takeover", None)) + if client_no_context_takeover: + params.append(("client_no_context_takeover", None)) + if server_max_window_bits: + params.append(("server_max_window_bits", str(server_max_window_bits))) + if client_max_window_bits is True: # only in handshake requests + params.append(("client_max_window_bits", None)) + elif client_max_window_bits: + params.append(("client_max_window_bits", str(client_max_window_bits))) + return params + + +def _extract_parameters( + params: Sequence[ExtensionParameter], *, is_server: bool +) -> Tuple[bool, bool, Optional[int], Optional[Union[int, bool]]]: + """ + Extract compression parameters from a list of ``(name, value)`` pairs. + + If ``is_server`` is :obj:`True`, ``client_max_window_bits`` may be + provided without a value. This is only allowed in handshake requests. + + """ + server_no_context_takeover: bool = False + client_no_context_takeover: bool = False + server_max_window_bits: Optional[int] = None + client_max_window_bits: Optional[Union[int, bool]] = None + + for name, value in params: + + if name == "server_no_context_takeover": + if server_no_context_takeover: + raise exceptions.DuplicateParameter(name) + if value is None: + server_no_context_takeover = True + else: + raise exceptions.InvalidParameterValue(name, value) + + elif name == "client_no_context_takeover": + if client_no_context_takeover: + raise exceptions.DuplicateParameter(name) + if value is None: + client_no_context_takeover = True + else: + raise exceptions.InvalidParameterValue(name, value) + + elif name == "server_max_window_bits": + if server_max_window_bits is not None: + raise exceptions.DuplicateParameter(name) + if value in _MAX_WINDOW_BITS_VALUES: + server_max_window_bits = int(value) + else: + raise exceptions.InvalidParameterValue(name, value) + + elif name == "client_max_window_bits": + if client_max_window_bits is not None: + raise exceptions.DuplicateParameter(name) + if is_server and value is None: # only in handshake requests + client_max_window_bits = True + elif value in _MAX_WINDOW_BITS_VALUES: + client_max_window_bits = int(value) + else: + raise exceptions.InvalidParameterValue(name, value) + + else: + raise exceptions.InvalidParameterName(name) + + return ( + server_no_context_takeover, + client_no_context_takeover, + server_max_window_bits, + client_max_window_bits, + ) + + +class ClientPerMessageDeflateFactory(ClientExtensionFactory): + """ + Client-side extension factory for the Per-Message Deflate extension. + + Parameters behave as described in `section 7.1 of RFC 7692`_. + + .. _section 7.1 of RFC 7692: https://www.rfc-editor.org/rfc/rfc7692.html#section-7.1 + + Set them to :obj:`True` to include them in the negotiation offer without a + value or to an integer value to include them with this value. + + Args: + server_no_context_takeover: prevent server from using context takeover. + client_no_context_takeover: prevent client from using context takeover. + server_max_window_bits: maximum size of the server's LZ77 sliding window + in bits, between 8 and 15. + client_max_window_bits: maximum size of the client's LZ77 sliding window + in bits, between 8 and 15, or :obj:`True` to indicate support without + setting a limit. + compress_settings: additional keyword arguments for :func:`zlib.compressobj`, + excluding ``wbits``. + + """ + + name = ExtensionName("permessage-deflate") + + def __init__( + self, + server_no_context_takeover: bool = False, + client_no_context_takeover: bool = False, + server_max_window_bits: Optional[int] = None, + client_max_window_bits: Optional[Union[int, bool]] = True, + compress_settings: Optional[Dict[str, Any]] = None, + ) -> None: + """ + Configure the Per-Message Deflate extension factory. + + """ + if not (server_max_window_bits is None or 8 <= server_max_window_bits <= 15): + raise ValueError("server_max_window_bits must be between 8 and 15") + if not ( + client_max_window_bits is None + or client_max_window_bits is True + or 8 <= client_max_window_bits <= 15 + ): + raise ValueError("client_max_window_bits must be between 8 and 15") + if compress_settings is not None and "wbits" in compress_settings: + raise ValueError( + "compress_settings must not include wbits, " + "set client_max_window_bits instead" + ) + + self.server_no_context_takeover = server_no_context_takeover + self.client_no_context_takeover = client_no_context_takeover + self.server_max_window_bits = server_max_window_bits + self.client_max_window_bits = client_max_window_bits + self.compress_settings = compress_settings + + def get_request_params(self) -> List[ExtensionParameter]: + """ + Build request parameters. + + """ + return _build_parameters( + self.server_no_context_takeover, + self.client_no_context_takeover, + self.server_max_window_bits, + self.client_max_window_bits, + ) + + def process_response_params( + self, + params: Sequence[ExtensionParameter], + accepted_extensions: Sequence[Extension], + ) -> PerMessageDeflate: + """ + Process response parameters. + + Return an extension instance. + + """ + if any(other.name == self.name for other in accepted_extensions): + raise exceptions.NegotiationError(f"received duplicate {self.name}") + + # Request parameters are available in instance variables. + + # Load response parameters in local variables. + ( + server_no_context_takeover, + client_no_context_takeover, + server_max_window_bits, + client_max_window_bits, + ) = _extract_parameters(params, is_server=False) + + # After comparing the request and the response, the final + # configuration must be available in the local variables. + + # server_no_context_takeover + # + # Req. Resp. Result + # ------ ------ -------------------------------------------------- + # False False False + # False True True + # True False Error! + # True True True + + if self.server_no_context_takeover: + if not server_no_context_takeover: + raise exceptions.NegotiationError("expected server_no_context_takeover") + + # client_no_context_takeover + # + # Req. Resp. Result + # ------ ------ -------------------------------------------------- + # False False False + # False True True + # True False True - must change value + # True True True + + if self.client_no_context_takeover: + if not client_no_context_takeover: + client_no_context_takeover = True + + # server_max_window_bits + + # Req. Resp. Result + # ------ ------ -------------------------------------------------- + # None None None + # None 8≤M≤15 M + # 8≤N≤15 None Error! + # 8≤N≤15 8≤M≤N M + # 8≤N≤15 N self.server_max_window_bits: + raise exceptions.NegotiationError("unsupported server_max_window_bits") + + # client_max_window_bits + + # Req. Resp. Result + # ------ ------ -------------------------------------------------- + # None None None + # None 8≤M≤15 Error! + # True None None + # True 8≤M≤15 M + # 8≤N≤15 None N - must change value + # 8≤N≤15 8≤M≤N M + # 8≤N≤15 N self.client_max_window_bits: + raise exceptions.NegotiationError("unsupported client_max_window_bits") + + return PerMessageDeflate( + server_no_context_takeover, # remote_no_context_takeover + client_no_context_takeover, # local_no_context_takeover + server_max_window_bits or 15, # remote_max_window_bits + client_max_window_bits or 15, # local_max_window_bits + self.compress_settings, + ) + + +def enable_client_permessage_deflate( + extensions: Optional[Sequence[ClientExtensionFactory]], +) -> Sequence[ClientExtensionFactory]: + """ + Enable Per-Message Deflate with default settings in client extensions. + + If the extension is already present, perhaps with non-default settings, + the configuration isn't changed. + + """ + if extensions is None: + extensions = [] + if not any( + extension_factory.name == ClientPerMessageDeflateFactory.name + for extension_factory in extensions + ): + extensions = list(extensions) + [ + ClientPerMessageDeflateFactory( + compress_settings={"memLevel": 5}, + ) + ] + return extensions + + +class ServerPerMessageDeflateFactory(ServerExtensionFactory): + """ + Server-side extension factory for the Per-Message Deflate extension. + + Parameters behave as described in `section 7.1 of RFC 7692`_. + + .. _section 7.1 of RFC 7692: https://www.rfc-editor.org/rfc/rfc7692.html#section-7.1 + + Set them to :obj:`True` to include them in the negotiation offer without a + value or to an integer value to include them with this value. + + Args: + server_no_context_takeover: prevent server from using context takeover. + client_no_context_takeover: prevent client from using context takeover. + server_max_window_bits: maximum size of the server's LZ77 sliding window + in bits, between 8 and 15. + client_max_window_bits: maximum size of the client's LZ77 sliding window + in bits, between 8 and 15. + compress_settings: additional keyword arguments for :func:`zlib.compressobj`, + excluding ``wbits``. + require_client_max_window_bits: do not enable compression at all if + client doesn't advertise support for ``client_max_window_bits``; + the default behavior is to enable compression without enforcing + ``client_max_window_bits``. + + """ + + name = ExtensionName("permessage-deflate") + + def __init__( + self, + server_no_context_takeover: bool = False, + client_no_context_takeover: bool = False, + server_max_window_bits: Optional[int] = None, + client_max_window_bits: Optional[int] = None, + compress_settings: Optional[Dict[str, Any]] = None, + require_client_max_window_bits: bool = False, + ) -> None: + """ + Configure the Per-Message Deflate extension factory. + + """ + if not (server_max_window_bits is None or 8 <= server_max_window_bits <= 15): + raise ValueError("server_max_window_bits must be between 8 and 15") + if not (client_max_window_bits is None or 8 <= client_max_window_bits <= 15): + raise ValueError("client_max_window_bits must be between 8 and 15") + if compress_settings is not None and "wbits" in compress_settings: + raise ValueError( + "compress_settings must not include wbits, " + "set server_max_window_bits instead" + ) + if client_max_window_bits is None and require_client_max_window_bits: + raise ValueError( + "require_client_max_window_bits is enabled, " + "but client_max_window_bits isn't configured" + ) + + self.server_no_context_takeover = server_no_context_takeover + self.client_no_context_takeover = client_no_context_takeover + self.server_max_window_bits = server_max_window_bits + self.client_max_window_bits = client_max_window_bits + self.compress_settings = compress_settings + self.require_client_max_window_bits = require_client_max_window_bits + + def process_request_params( + self, + params: Sequence[ExtensionParameter], + accepted_extensions: Sequence[Extension], + ) -> Tuple[List[ExtensionParameter], PerMessageDeflate]: + """ + Process request parameters. + + Return response params and an extension instance. + + """ + if any(other.name == self.name for other in accepted_extensions): + raise exceptions.NegotiationError(f"skipped duplicate {self.name}") + + # Load request parameters in local variables. + ( + server_no_context_takeover, + client_no_context_takeover, + server_max_window_bits, + client_max_window_bits, + ) = _extract_parameters(params, is_server=True) + + # Configuration parameters are available in instance variables. + + # After comparing the request and the configuration, the response must + # be available in the local variables. + + # server_no_context_takeover + # + # Config Req. Resp. + # ------ ------ -------------------------------------------------- + # False False False + # False True True + # True False True - must change value to True + # True True True + + if self.server_no_context_takeover: + if not server_no_context_takeover: + server_no_context_takeover = True + + # client_no_context_takeover + # + # Config Req. Resp. + # ------ ------ -------------------------------------------------- + # False False False + # False True True (or False) + # True False True - must change value to True + # True True True (or False) + + if self.client_no_context_takeover: + if not client_no_context_takeover: + client_no_context_takeover = True + + # server_max_window_bits + + # Config Req. Resp. + # ------ ------ -------------------------------------------------- + # None None None + # None 8≤M≤15 M + # 8≤N≤15 None N - must change value + # 8≤N≤15 8≤M≤N M + # 8≤N≤15 N self.server_max_window_bits: + server_max_window_bits = self.server_max_window_bits + + # client_max_window_bits + + # Config Req. Resp. + # ------ ------ -------------------------------------------------- + # None None None + # None True None - must change value + # None 8≤M≤15 M (or None) + # 8≤N≤15 None None or Error! + # 8≤N≤15 True N - must change value + # 8≤N≤15 8≤M≤N M (or None) + # 8≤N≤15 N Sequence[ServerExtensionFactory]: + """ + Enable Per-Message Deflate with default settings in server extensions. + + If the extension is already present, perhaps with non-default settings, + the configuration isn't changed. + + """ + if extensions is None: + extensions = [] + if not any( + ext_factory.name == ServerPerMessageDeflateFactory.name + for ext_factory in extensions + ): + extensions = list(extensions) + [ + ServerPerMessageDeflateFactory( + server_max_window_bits=12, + client_max_window_bits=12, + compress_settings={"memLevel": 5}, + ) + ] + return extensions diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/frames.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/frames.py new file mode 100644 index 00000000..043b688b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/frames.py @@ -0,0 +1,443 @@ +from __future__ import annotations + +import dataclasses +import enum +import io +import secrets +import struct +from typing import Callable, Generator, Optional, Sequence, Tuple + +from . import exceptions, extensions +from .typing import Data + + +try: + from .speedups import apply_mask +except ImportError: # pragma: no cover + from .utils import apply_mask + + +__all__ = [ + "Opcode", + "OP_CONT", + "OP_TEXT", + "OP_BINARY", + "OP_CLOSE", + "OP_PING", + "OP_PONG", + "DATA_OPCODES", + "CTRL_OPCODES", + "Frame", + "prepare_data", + "prepare_ctrl", + "Close", +] + + +class Opcode(enum.IntEnum): + """Opcode values for WebSocket frames.""" + + CONT, TEXT, BINARY = 0x00, 0x01, 0x02 + CLOSE, PING, PONG = 0x08, 0x09, 0x0A + + +OP_CONT = Opcode.CONT +OP_TEXT = Opcode.TEXT +OP_BINARY = Opcode.BINARY +OP_CLOSE = Opcode.CLOSE +OP_PING = Opcode.PING +OP_PONG = Opcode.PONG + +DATA_OPCODES = OP_CONT, OP_TEXT, OP_BINARY +CTRL_OPCODES = OP_CLOSE, OP_PING, OP_PONG + + +# See https://www.iana.org/assignments/websocket/websocket.xhtml +CLOSE_CODES = { + 1000: "OK", + 1001: "going away", + 1002: "protocol error", + 1003: "unsupported type", + # 1004 is reserved + 1005: "no status code [internal]", + 1006: "connection closed abnormally [internal]", + 1007: "invalid data", + 1008: "policy violation", + 1009: "message too big", + 1010: "extension required", + 1011: "unexpected error", + 1012: "service restart", + 1013: "try again later", + 1014: "bad gateway", + 1015: "TLS failure [internal]", +} + + +# Close code that are allowed in a close frame. +# Using a set optimizes `code in EXTERNAL_CLOSE_CODES`. +EXTERNAL_CLOSE_CODES = { + 1000, + 1001, + 1002, + 1003, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, +} + +OK_CLOSE_CODES = {1000, 1001} + + +BytesLike = bytes, bytearray, memoryview + + +@dataclasses.dataclass +class Frame: + """ + WebSocket frame. + + Attributes: + opcode: Opcode. + data: Payload data. + fin: FIN bit. + rsv1: RSV1 bit. + rsv2: RSV2 bit. + rsv3: RSV3 bit. + + Only these fields are needed. The MASK bit, payload length and masking-key + are handled on the fly when parsing and serializing frames. + + """ + + opcode: Opcode + data: bytes + fin: bool = True + rsv1: bool = False + rsv2: bool = False + rsv3: bool = False + + def __str__(self) -> str: + """ + Return a human-readable represention of a frame. + + """ + coding = None + length = f"{len(self.data)} byte{'' if len(self.data) == 1 else 's'}" + non_final = "" if self.fin else "continued" + + if self.opcode is OP_TEXT: + # Decoding only the beginning and the end is needlessly hard. + # Decode the entire payload then elide later if necessary. + data = repr(self.data.decode()) + elif self.opcode is OP_BINARY: + # We'll show at most the first 16 bytes and the last 8 bytes. + # Encode just what we need, plus two dummy bytes to elide later. + binary = self.data + if len(binary) > 25: + binary = b"".join([binary[:16], b"\x00\x00", binary[-8:]]) + data = " ".join(f"{byte:02x}" for byte in binary) + elif self.opcode is OP_CLOSE: + data = str(Close.parse(self.data)) + elif self.data: + # We don't know if a Continuation frame contains text or binary. + # Ping and Pong frames could contain UTF-8. + # Attempt to decode as UTF-8 and display it as text; fallback to + # binary. If self.data is a memoryview, it has no decode() method, + # which raises AttributeError. + try: + data = repr(self.data.decode()) + coding = "text" + except (UnicodeDecodeError, AttributeError): + binary = self.data + if len(binary) > 25: + binary = b"".join([binary[:16], b"\x00\x00", binary[-8:]]) + data = " ".join(f"{byte:02x}" for byte in binary) + coding = "binary" + else: + data = "''" + + if len(data) > 75: + data = data[:48] + "..." + data[-24:] + + metadata = ", ".join(filter(None, [coding, length, non_final])) + + return f"{self.opcode.name} {data} [{metadata}]" + + @classmethod + def parse( + cls, + read_exact: Callable[[int], Generator[None, None, bytes]], + *, + mask: bool, + max_size: Optional[int] = None, + extensions: Optional[Sequence[extensions.Extension]] = None, + ) -> Generator[None, None, Frame]: + """ + Parse a WebSocket frame. + + This is a generator-based coroutine. + + Args: + read_exact: generator-based coroutine that reads the requested + bytes or raises an exception if there isn't enough data. + mask: whether the frame should be masked i.e. whether the read + happens on the server side. + max_size: maximum payload size in bytes. + extensions: list of extensions, applied in reverse order. + + Raises: + PayloadTooBig: if the frame's payload size exceeds ``max_size``. + ProtocolError: if the frame contains incorrect values. + + """ + # Read the header. + data = yield from read_exact(2) + head1, head2 = struct.unpack("!BB", data) + + # While not Pythonic, this is marginally faster than calling bool(). + fin = True if head1 & 0b10000000 else False + rsv1 = True if head1 & 0b01000000 else False + rsv2 = True if head1 & 0b00100000 else False + rsv3 = True if head1 & 0b00010000 else False + + try: + opcode = Opcode(head1 & 0b00001111) + except ValueError as exc: + raise exceptions.ProtocolError("invalid opcode") from exc + + if (True if head2 & 0b10000000 else False) != mask: + raise exceptions.ProtocolError("incorrect masking") + + length = head2 & 0b01111111 + if length == 126: + data = yield from read_exact(2) + (length,) = struct.unpack("!H", data) + elif length == 127: + data = yield from read_exact(8) + (length,) = struct.unpack("!Q", data) + if max_size is not None and length > max_size: + raise exceptions.PayloadTooBig( + f"over size limit ({length} > {max_size} bytes)" + ) + if mask: + mask_bytes = yield from read_exact(4) + + # Read the data. + data = yield from read_exact(length) + if mask: + data = apply_mask(data, mask_bytes) + + frame = cls(opcode, data, fin, rsv1, rsv2, rsv3) + + if extensions is None: + extensions = [] + for extension in reversed(extensions): + frame = extension.decode(frame, max_size=max_size) + + frame.check() + + return frame + + def serialize( + self, + *, + mask: bool, + extensions: Optional[Sequence[extensions.Extension]] = None, + ) -> bytes: + """ + Serialize a WebSocket frame. + + Args: + mask: whether the frame should be masked i.e. whether the write + happens on the client side. + extensions: list of extensions, applied in order. + + Raises: + ProtocolError: if the frame contains incorrect values. + + """ + self.check() + + if extensions is None: + extensions = [] + for extension in extensions: + self = extension.encode(self) + + output = io.BytesIO() + + # Prepare the header. + head1 = ( + (0b10000000 if self.fin else 0) + | (0b01000000 if self.rsv1 else 0) + | (0b00100000 if self.rsv2 else 0) + | (0b00010000 if self.rsv3 else 0) + | self.opcode + ) + + head2 = 0b10000000 if mask else 0 + + length = len(self.data) + if length < 126: + output.write(struct.pack("!BB", head1, head2 | length)) + elif length < 65536: + output.write(struct.pack("!BBH", head1, head2 | 126, length)) + else: + output.write(struct.pack("!BBQ", head1, head2 | 127, length)) + + if mask: + mask_bytes = secrets.token_bytes(4) + output.write(mask_bytes) + + # Prepare the data. + if mask: + data = apply_mask(self.data, mask_bytes) + else: + data = self.data + output.write(data) + + return output.getvalue() + + def check(self) -> None: + """ + Check that reserved bits and opcode have acceptable values. + + Raises: + ProtocolError: if a reserved bit or the opcode is invalid. + + """ + if self.rsv1 or self.rsv2 or self.rsv3: + raise exceptions.ProtocolError("reserved bits must be 0") + + if self.opcode in CTRL_OPCODES: + if len(self.data) > 125: + raise exceptions.ProtocolError("control frame too long") + if not self.fin: + raise exceptions.ProtocolError("fragmented control frame") + + +def prepare_data(data: Data) -> Tuple[int, bytes]: + """ + Convert a string or byte-like object to an opcode and a bytes-like object. + + This function is designed for data frames. + + If ``data`` is a :class:`str`, return ``OP_TEXT`` and a :class:`bytes` + object encoding ``data`` in UTF-8. + + If ``data`` is a bytes-like object, return ``OP_BINARY`` and a bytes-like + object. + + Raises: + TypeError: if ``data`` doesn't have a supported type. + + """ + if isinstance(data, str): + return OP_TEXT, data.encode("utf-8") + elif isinstance(data, BytesLike): + return OP_BINARY, data + else: + raise TypeError("data must be str or bytes-like") + + +def prepare_ctrl(data: Data) -> bytes: + """ + Convert a string or byte-like object to bytes. + + This function is designed for ping and pong frames. + + If ``data`` is a :class:`str`, return a :class:`bytes` object encoding + ``data`` in UTF-8. + + If ``data`` is a bytes-like object, return a :class:`bytes` object. + + Raises: + TypeError: if ``data`` doesn't have a supported type. + + """ + if isinstance(data, str): + return data.encode("utf-8") + elif isinstance(data, BytesLike): + return bytes(data) + else: + raise TypeError("data must be str or bytes-like") + + +@dataclasses.dataclass +class Close: + """ + Code and reason for WebSocket close frames. + + Attributes: + code: Close code. + reason: Close reason. + + """ + + code: int + reason: str + + def __str__(self) -> str: + """ + Return a human-readable represention of a close code and reason. + + """ + if 3000 <= self.code < 4000: + explanation = "registered" + elif 4000 <= self.code < 5000: + explanation = "private use" + else: + explanation = CLOSE_CODES.get(self.code, "unknown") + result = f"{self.code} ({explanation})" + + if self.reason: + result = f"{result} {self.reason}" + + return result + + @classmethod + def parse(cls, data: bytes) -> Close: + """ + Parse the payload of a close frame. + + Args: + data: payload of the close frame. + + Raises: + ProtocolError: if data is ill-formed. + UnicodeDecodeError: if the reason isn't valid UTF-8. + + """ + if len(data) >= 2: + (code,) = struct.unpack("!H", data[:2]) + reason = data[2:].decode("utf-8") + close = cls(code, reason) + close.check() + return close + elif len(data) == 0: + return cls(1005, "") + else: + raise exceptions.ProtocolError("close frame too short") + + def serialize(self) -> bytes: + """ + Serialize the payload of a close frame. + + """ + self.check() + return struct.pack("!H", self.code) + self.reason.encode("utf-8") + + def check(self) -> None: + """ + Check that the close code has a valid value for a close frame. + + Raises: + ProtocolError: if the close code is invalid. + + """ + if not (self.code in EXTERNAL_CLOSE_CODES or 3000 <= self.code < 5000): + raise exceptions.ProtocolError("invalid status code") diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/headers.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/headers.py new file mode 100644 index 00000000..9ae3035a --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/headers.py @@ -0,0 +1,587 @@ +from __future__ import annotations + +import base64 +import binascii +import ipaddress +import re +from typing import Callable, List, Optional, Sequence, Tuple, TypeVar, cast + +from . import exceptions +from .typing import ( + ConnectionOption, + ExtensionHeader, + ExtensionName, + ExtensionParameter, + Subprotocol, + UpgradeProtocol, +) + + +__all__ = [ + "build_host", + "parse_connection", + "parse_upgrade", + "parse_extension", + "build_extension", + "parse_subprotocol", + "build_subprotocol", + "validate_subprotocols", + "build_www_authenticate_basic", + "parse_authorization_basic", + "build_authorization_basic", +] + + +T = TypeVar("T") + + +def build_host(host: str, port: int, secure: bool) -> str: + """ + Build a ``Host`` header. + + """ + # https://www.rfc-editor.org/rfc/rfc3986.html#section-3.2.2 + # IPv6 addresses must be enclosed in brackets. + try: + address = ipaddress.ip_address(host) + except ValueError: + # host is a hostname + pass + else: + # host is an IP address + if address.version == 6: + host = f"[{host}]" + + if port != (443 if secure else 80): + host = f"{host}:{port}" + + return host + + +# To avoid a dependency on a parsing library, we implement manually the ABNF +# described in https://www.rfc-editor.org/rfc/rfc6455.html#section-9.1 and +# https://www.rfc-editor.org/rfc/rfc7230.html#appendix-B. + + +def peek_ahead(header: str, pos: int) -> Optional[str]: + """ + Return the next character from ``header`` at the given position. + + Return :obj:`None` at the end of ``header``. + + We never need to peek more than one character ahead. + + """ + return None if pos == len(header) else header[pos] + + +_OWS_re = re.compile(r"[\t ]*") + + +def parse_OWS(header: str, pos: int) -> int: + """ + Parse optional whitespace from ``header`` at the given position. + + Return the new position. + + The whitespace itself isn't returned because it isn't significant. + + """ + # There's always a match, possibly empty, whose content doesn't matter. + match = _OWS_re.match(header, pos) + assert match is not None + return match.end() + + +_token_re = re.compile(r"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+") + + +def parse_token(header: str, pos: int, header_name: str) -> Tuple[str, int]: + """ + Parse a token from ``header`` at the given position. + + Return the token value and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + match = _token_re.match(header, pos) + if match is None: + raise exceptions.InvalidHeaderFormat(header_name, "expected token", header, pos) + return match.group(), match.end() + + +_quoted_string_re = re.compile( + r'"(?:[\x09\x20-\x21\x23-\x5b\x5d-\x7e]|\\[\x09\x20-\x7e\x80-\xff])*"' +) + + +_unquote_re = re.compile(r"\\([\x09\x20-\x7e\x80-\xff])") + + +def parse_quoted_string(header: str, pos: int, header_name: str) -> Tuple[str, int]: + """ + Parse a quoted string from ``header`` at the given position. + + Return the unquoted value and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + match = _quoted_string_re.match(header, pos) + if match is None: + raise exceptions.InvalidHeaderFormat( + header_name, "expected quoted string", header, pos + ) + return _unquote_re.sub(r"\1", match.group()[1:-1]), match.end() + + +_quotable_re = re.compile(r"[\x09\x20-\x7e\x80-\xff]*") + + +_quote_re = re.compile(r"([\x22\x5c])") + + +def build_quoted_string(value: str) -> str: + """ + Format ``value`` as a quoted string. + + This is the reverse of :func:`parse_quoted_string`. + + """ + match = _quotable_re.fullmatch(value) + if match is None: + raise ValueError("invalid characters for quoted-string encoding") + return '"' + _quote_re.sub(r"\\\1", value) + '"' + + +def parse_list( + parse_item: Callable[[str, int, str], Tuple[T, int]], + header: str, + pos: int, + header_name: str, +) -> List[T]: + """ + Parse a comma-separated list from ``header`` at the given position. + + This is appropriate for parsing values with the following grammar: + + 1#item + + ``parse_item`` parses one item. + + ``header`` is assumed not to start or end with whitespace. + + (This function is designed for parsing an entire header value and + :func:`~websockets.http.read_headers` strips whitespace from values.) + + Return a list of items. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + # Per https://www.rfc-editor.org/rfc/rfc7230.html#section-7, "a recipient + # MUST parse and ignore a reasonable number of empty list elements"; + # hence while loops that remove extra delimiters. + + # Remove extra delimiters before the first item. + while peek_ahead(header, pos) == ",": + pos = parse_OWS(header, pos + 1) + + items = [] + while True: + # Loop invariant: a item starts at pos in header. + item, pos = parse_item(header, pos, header_name) + items.append(item) + pos = parse_OWS(header, pos) + + # We may have reached the end of the header. + if pos == len(header): + break + + # There must be a delimiter after each element except the last one. + if peek_ahead(header, pos) == ",": + pos = parse_OWS(header, pos + 1) + else: + raise exceptions.InvalidHeaderFormat( + header_name, "expected comma", header, pos + ) + + # Remove extra delimiters before the next item. + while peek_ahead(header, pos) == ",": + pos = parse_OWS(header, pos + 1) + + # We may have reached the end of the header. + if pos == len(header): + break + + # Since we only advance in the header by one character with peek_ahead() + # or with the end position of a regex match, we can't overshoot the end. + assert pos == len(header) + + return items + + +def parse_connection_option( + header: str, pos: int, header_name: str +) -> Tuple[ConnectionOption, int]: + """ + Parse a Connection option from ``header`` at the given position. + + Return the protocol value and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + item, pos = parse_token(header, pos, header_name) + return cast(ConnectionOption, item), pos + + +def parse_connection(header: str) -> List[ConnectionOption]: + """ + Parse a ``Connection`` header. + + Return a list of HTTP connection options. + + Args + header: value of the ``Connection`` header. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + return parse_list(parse_connection_option, header, 0, "Connection") + + +_protocol_re = re.compile( + r"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+(?:/[-!#$%&\'*+.^_`|~0-9a-zA-Z]+)?" +) + + +def parse_upgrade_protocol( + header: str, pos: int, header_name: str +) -> Tuple[UpgradeProtocol, int]: + """ + Parse an Upgrade protocol from ``header`` at the given position. + + Return the protocol value and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + match = _protocol_re.match(header, pos) + if match is None: + raise exceptions.InvalidHeaderFormat( + header_name, "expected protocol", header, pos + ) + return cast(UpgradeProtocol, match.group()), match.end() + + +def parse_upgrade(header: str) -> List[UpgradeProtocol]: + """ + Parse an ``Upgrade`` header. + + Return a list of HTTP protocols. + + Args: + header: value of the ``Upgrade`` header. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + return parse_list(parse_upgrade_protocol, header, 0, "Upgrade") + + +def parse_extension_item_param( + header: str, pos: int, header_name: str +) -> Tuple[ExtensionParameter, int]: + """ + Parse a single extension parameter from ``header`` at the given position. + + Return a ``(name, value)`` pair and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + # Extract parameter name. + name, pos = parse_token(header, pos, header_name) + pos = parse_OWS(header, pos) + # Extract parameter value, if there is one. + value: Optional[str] = None + if peek_ahead(header, pos) == "=": + pos = parse_OWS(header, pos + 1) + if peek_ahead(header, pos) == '"': + pos_before = pos # for proper error reporting below + value, pos = parse_quoted_string(header, pos, header_name) + # https://www.rfc-editor.org/rfc/rfc6455.html#section-9.1 says: + # the value after quoted-string unescaping MUST conform to + # the 'token' ABNF. + if _token_re.fullmatch(value) is None: + raise exceptions.InvalidHeaderFormat( + header_name, "invalid quoted header content", header, pos_before + ) + else: + value, pos = parse_token(header, pos, header_name) + pos = parse_OWS(header, pos) + + return (name, value), pos + + +def parse_extension_item( + header: str, pos: int, header_name: str +) -> Tuple[ExtensionHeader, int]: + """ + Parse an extension definition from ``header`` at the given position. + + Return an ``(extension name, parameters)`` pair, where ``parameters`` is a + list of ``(name, value)`` pairs, and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + # Extract extension name. + name, pos = parse_token(header, pos, header_name) + pos = parse_OWS(header, pos) + # Extract all parameters. + parameters = [] + while peek_ahead(header, pos) == ";": + pos = parse_OWS(header, pos + 1) + parameter, pos = parse_extension_item_param(header, pos, header_name) + parameters.append(parameter) + return (cast(ExtensionName, name), parameters), pos + + +def parse_extension(header: str) -> List[ExtensionHeader]: + """ + Parse a ``Sec-WebSocket-Extensions`` header. + + Return a list of WebSocket extensions and their parameters in this format:: + + [ + ( + 'extension name', + [ + ('parameter name', 'parameter value'), + .... + ] + ), + ... + ] + + Parameter values are :obj:`None` when no value is provided. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + return parse_list(parse_extension_item, header, 0, "Sec-WebSocket-Extensions") + + +parse_extension_list = parse_extension # alias for backwards compatibility + + +def build_extension_item( + name: ExtensionName, parameters: List[ExtensionParameter] +) -> str: + """ + Build an extension definition. + + This is the reverse of :func:`parse_extension_item`. + + """ + return "; ".join( + [cast(str, name)] + + [ + # Quoted strings aren't necessary because values are always tokens. + name if value is None else f"{name}={value}" + for name, value in parameters + ] + ) + + +def build_extension(extensions: Sequence[ExtensionHeader]) -> str: + """ + Build a ``Sec-WebSocket-Extensions`` header. + + This is the reverse of :func:`parse_extension`. + + """ + return ", ".join( + build_extension_item(name, parameters) for name, parameters in extensions + ) + + +build_extension_list = build_extension # alias for backwards compatibility + + +def parse_subprotocol_item( + header: str, pos: int, header_name: str +) -> Tuple[Subprotocol, int]: + """ + Parse a subprotocol from ``header`` at the given position. + + Return the subprotocol value and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + item, pos = parse_token(header, pos, header_name) + return cast(Subprotocol, item), pos + + +def parse_subprotocol(header: str) -> List[Subprotocol]: + """ + Parse a ``Sec-WebSocket-Protocol`` header. + + Return a list of WebSocket subprotocols. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + return parse_list(parse_subprotocol_item, header, 0, "Sec-WebSocket-Protocol") + + +parse_subprotocol_list = parse_subprotocol # alias for backwards compatibility + + +def build_subprotocol(subprotocols: Sequence[Subprotocol]) -> str: + """ + Build a ``Sec-WebSocket-Protocol`` header. + + This is the reverse of :func:`parse_subprotocol`. + + """ + return ", ".join(subprotocols) + + +build_subprotocol_list = build_subprotocol # alias for backwards compatibility + + +def validate_subprotocols(subprotocols: Sequence[Subprotocol]) -> None: + """ + Validate that ``subprotocols`` is suitable for :func:`build_subprotocol`. + + """ + if not isinstance(subprotocols, Sequence): + raise TypeError("subprotocols must be a list") + if isinstance(subprotocols, str): + raise TypeError("subprotocols must be a list, not a str") + for subprotocol in subprotocols: + if not _token_re.fullmatch(subprotocol): + raise ValueError(f"invalid subprotocol: {subprotocol}") + + +def build_www_authenticate_basic(realm: str) -> str: + """ + Build a ``WWW-Authenticate`` header for HTTP Basic Auth. + + Args: + realm: identifier of the protection space. + + """ + # https://www.rfc-editor.org/rfc/rfc7617.html#section-2 + realm = build_quoted_string(realm) + charset = build_quoted_string("UTF-8") + return f"Basic realm={realm}, charset={charset}" + + +_token68_re = re.compile(r"[A-Za-z0-9-._~+/]+=*") + + +def parse_token68(header: str, pos: int, header_name: str) -> Tuple[str, int]: + """ + Parse a token68 from ``header`` at the given position. + + Return the token value and the new position. + + Raises: + InvalidHeaderFormat: on invalid inputs. + + """ + match = _token68_re.match(header, pos) + if match is None: + raise exceptions.InvalidHeaderFormat( + header_name, "expected token68", header, pos + ) + return match.group(), match.end() + + +def parse_end(header: str, pos: int, header_name: str) -> None: + """ + Check that parsing reached the end of header. + + """ + if pos < len(header): + raise exceptions.InvalidHeaderFormat(header_name, "trailing data", header, pos) + + +def parse_authorization_basic(header: str) -> Tuple[str, str]: + """ + Parse an ``Authorization`` header for HTTP Basic Auth. + + Return a ``(username, password)`` tuple. + + Args: + header: value of the ``Authorization`` header. + + Raises: + InvalidHeaderFormat: on invalid inputs. + InvalidHeaderValue: on unsupported inputs. + + """ + # https://www.rfc-editor.org/rfc/rfc7235.html#section-2.1 + # https://www.rfc-editor.org/rfc/rfc7617.html#section-2 + scheme, pos = parse_token(header, 0, "Authorization") + if scheme.lower() != "basic": + raise exceptions.InvalidHeaderValue( + "Authorization", + f"unsupported scheme: {scheme}", + ) + if peek_ahead(header, pos) != " ": + raise exceptions.InvalidHeaderFormat( + "Authorization", "expected space after scheme", header, pos + ) + pos += 1 + basic_credentials, pos = parse_token68(header, pos, "Authorization") + parse_end(header, pos, "Authorization") + + try: + user_pass = base64.b64decode(basic_credentials.encode()).decode() + except binascii.Error: + raise exceptions.InvalidHeaderValue( + "Authorization", + "expected base64-encoded credentials", + ) from None + try: + username, password = user_pass.split(":", 1) + except ValueError: + raise exceptions.InvalidHeaderValue( + "Authorization", + "expected username:password credentials", + ) from None + + return username, password + + +def build_authorization_basic(username: str, password: str) -> str: + """ + Build an ``Authorization`` header for HTTP Basic Auth. + + This is the reverse of :func:`parse_authorization_basic`. + + """ + # https://www.rfc-editor.org/rfc/rfc7617.html#section-2 + assert ":" not in username + user_pass = f"{username}:{password}" + basic_credentials = base64.b64encode(user_pass.encode()).decode() + return "Basic " + basic_credentials diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http.py new file mode 100644 index 00000000..b14fa94b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +import sys + +from .imports import lazy_import +from .version import version as websockets_version + + +# For backwards compatibility: + + +lazy_import( + globals(), + # Headers and MultipleValuesError used to be defined in this module. + aliases={ + "Headers": ".datastructures", + "MultipleValuesError": ".datastructures", + }, + deprecated_aliases={ + "read_request": ".legacy.http", + "read_response": ".legacy.http", + }, +) + + +__all__ = ["USER_AGENT"] + + +PYTHON_VERSION = "{}.{}".format(*sys.version_info) +USER_AGENT = f"Python/{PYTHON_VERSION} websockets/{websockets_version}" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http11.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http11.py new file mode 100644 index 00000000..84048fa4 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/http11.py @@ -0,0 +1,366 @@ +from __future__ import annotations + +import dataclasses +import re +import warnings +from typing import Callable, Generator, Optional + +from . import datastructures, exceptions + + +# Maximum total size of headers is around 256 * 4 KiB = 1 MiB +MAX_HEADERS = 256 + +# We can use the same limit for the request line and header lines: +# "GET <4096 bytes> HTTP/1.1\r\n" = 4111 bytes +# "Set-Cookie: <4097 bytes>\r\n" = 4111 bytes +# (RFC requires 4096 bytes; for some reason Firefox supports 4097 bytes.) +MAX_LINE = 4111 + +# Support for HTTP response bodies is intended to read an error message +# returned by a server. It isn't designed to perform large file transfers. +MAX_BODY = 2**20 # 1 MiB + + +def d(value: bytes) -> str: + """ + Decode a bytestring for interpolating into an error message. + + """ + return value.decode(errors="backslashreplace") + + +# See https://www.rfc-editor.org/rfc/rfc7230.html#appendix-B. + +# Regex for validating header names. + +_token_re = re.compile(rb"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+") + +# Regex for validating header values. + +# We don't attempt to support obsolete line folding. + +# Include HTAB (\x09), SP (\x20), VCHAR (\x21-\x7e), obs-text (\x80-\xff). + +# The ABNF is complicated because it attempts to express that optional +# whitespace is ignored. We strip whitespace and don't revalidate that. + +# See also https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189 + +_value_re = re.compile(rb"[\x09\x20-\x7e\x80-\xff]*") + + +@dataclasses.dataclass +class Request: + """ + WebSocket handshake request. + + Attributes: + path: Request path, including optional query. + headers: Request headers. + """ + + path: str + headers: datastructures.Headers + # body isn't useful is the context of this library. + + _exception: Optional[Exception] = None + + @property + def exception(self) -> Optional[Exception]: # pragma: no cover + warnings.warn( + "Request.exception is deprecated; " + "use ServerConnection.handshake_exc instead", + DeprecationWarning, + ) + return self._exception + + @classmethod + def parse( + cls, + read_line: Callable[[int], Generator[None, None, bytes]], + ) -> Generator[None, None, Request]: + """ + Parse a WebSocket handshake request. + + This is a generator-based coroutine. + + The request path isn't URL-decoded or validated in any way. + + The request path and headers are expected to contain only ASCII + characters. Other characters are represented with surrogate escapes. + + :meth:`parse` doesn't attempt to read the request body because + WebSocket handshake requests don't have one. If the request contains a + body, it may be read from the data stream after :meth:`parse` returns. + + Args: + read_line: generator-based coroutine that reads a LF-terminated + line or raises an exception if there isn't enough data + + Raises: + EOFError: if the connection is closed without a full HTTP request. + SecurityError: if the request exceeds a security limit. + ValueError: if the request isn't well formatted. + + """ + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.1 + + # Parsing is simple because fixed values are expected for method and + # version and because path isn't checked. Since WebSocket software tends + # to implement HTTP/1.1 strictly, there's little need for lenient parsing. + + try: + request_line = yield from parse_line(read_line) + except EOFError as exc: + raise EOFError("connection closed while reading HTTP request line") from exc + + try: + method, raw_path, version = request_line.split(b" ", 2) + except ValueError: # not enough values to unpack (expected 3, got 1-2) + raise ValueError(f"invalid HTTP request line: {d(request_line)}") from None + + if method != b"GET": + raise ValueError(f"unsupported HTTP method: {d(method)}") + if version != b"HTTP/1.1": + raise ValueError(f"unsupported HTTP version: {d(version)}") + path = raw_path.decode("ascii", "surrogateescape") + + headers = yield from parse_headers(read_line) + + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.3.3 + + if "Transfer-Encoding" in headers: + raise NotImplementedError("transfer codings aren't supported") + + if "Content-Length" in headers: + raise ValueError("unsupported request body") + + return cls(path, headers) + + def serialize(self) -> bytes: + """ + Serialize a WebSocket handshake request. + + """ + # Since the request line and headers only contain ASCII characters, + # we can keep this simple. + request = f"GET {self.path} HTTP/1.1\r\n".encode() + request += self.headers.serialize() + return request + + +@dataclasses.dataclass +class Response: + """ + WebSocket handshake response. + + Attributes: + status_code: Response code. + reason_phrase: Response reason. + headers: Response headers. + body: Response body, if any. + + """ + + status_code: int + reason_phrase: str + headers: datastructures.Headers + body: Optional[bytes] = None + + _exception: Optional[Exception] = None + + @property + def exception(self) -> Optional[Exception]: # pragma: no cover + warnings.warn( + "Response.exception is deprecated; " + "use ClientConnection.handshake_exc instead", + DeprecationWarning, + ) + return self._exception + + @classmethod + def parse( + cls, + read_line: Callable[[int], Generator[None, None, bytes]], + read_exact: Callable[[int], Generator[None, None, bytes]], + read_to_eof: Callable[[int], Generator[None, None, bytes]], + ) -> Generator[None, None, Response]: + """ + Parse a WebSocket handshake response. + + This is a generator-based coroutine. + + The reason phrase and headers are expected to contain only ASCII + characters. Other characters are represented with surrogate escapes. + + Args: + read_line: generator-based coroutine that reads a LF-terminated + line or raises an exception if there isn't enough data. + read_exact: generator-based coroutine that reads the requested + bytes or raises an exception if there isn't enough data. + read_to_eof: generator-based coroutine that reads until the end + of the stream. + + Raises: + EOFError: if the connection is closed without a full HTTP response. + SecurityError: if the response exceeds a security limit. + LookupError: if the response isn't well formatted. + ValueError: if the response isn't well formatted. + + """ + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.2 + + try: + status_line = yield from parse_line(read_line) + except EOFError as exc: + raise EOFError("connection closed while reading HTTP status line") from exc + + try: + version, raw_status_code, raw_reason = status_line.split(b" ", 2) + except ValueError: # not enough values to unpack (expected 3, got 1-2) + raise ValueError(f"invalid HTTP status line: {d(status_line)}") from None + + if version != b"HTTP/1.1": + raise ValueError(f"unsupported HTTP version: {d(version)}") + try: + status_code = int(raw_status_code) + except ValueError: # invalid literal for int() with base 10 + raise ValueError( + f"invalid HTTP status code: {d(raw_status_code)}" + ) from None + if not 100 <= status_code < 1000: + raise ValueError(f"unsupported HTTP status code: {d(raw_status_code)}") + if not _value_re.fullmatch(raw_reason): + raise ValueError(f"invalid HTTP reason phrase: {d(raw_reason)}") + reason = raw_reason.decode() + + headers = yield from parse_headers(read_line) + + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.3.3 + + if "Transfer-Encoding" in headers: + raise NotImplementedError("transfer codings aren't supported") + + # Since websockets only does GET requests (no HEAD, no CONNECT), all + # responses except 1xx, 204, and 304 include a message body. + if 100 <= status_code < 200 or status_code == 204 or status_code == 304: + body = None + else: + content_length: Optional[int] + try: + # MultipleValuesError is sufficiently unlikely that we don't + # attempt to handle it. Instead we document that its parent + # class, LookupError, may be raised. + raw_content_length = headers["Content-Length"] + except KeyError: + content_length = None + else: + content_length = int(raw_content_length) + + if content_length is None: + try: + body = yield from read_to_eof(MAX_BODY) + except RuntimeError: + raise exceptions.SecurityError( + f"body too large: over {MAX_BODY} bytes" + ) + elif content_length > MAX_BODY: + raise exceptions.SecurityError( + f"body too large: {content_length} bytes" + ) + else: + body = yield from read_exact(content_length) + + return cls(status_code, reason, headers, body) + + def serialize(self) -> bytes: + """ + Serialize a WebSocket handshake response. + + """ + # Since the status line and headers only contain ASCII characters, + # we can keep this simple. + response = f"HTTP/1.1 {self.status_code} {self.reason_phrase}\r\n".encode() + response += self.headers.serialize() + if self.body is not None: + response += self.body + return response + + +def parse_headers( + read_line: Callable[[int], Generator[None, None, bytes]], +) -> Generator[None, None, datastructures.Headers]: + """ + Parse HTTP headers. + + Non-ASCII characters are represented with surrogate escapes. + + Args: + read_line: generator-based coroutine that reads a LF-terminated line + or raises an exception if there isn't enough data. + + Raises: + EOFError: if the connection is closed without complete headers. + SecurityError: if the request exceeds a security limit. + ValueError: if the request isn't well formatted. + + """ + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2 + + # We don't attempt to support obsolete line folding. + + headers = datastructures.Headers() + for _ in range(MAX_HEADERS + 1): + try: + line = yield from parse_line(read_line) + except EOFError as exc: + raise EOFError("connection closed while reading HTTP headers") from exc + if line == b"": + break + + try: + raw_name, raw_value = line.split(b":", 1) + except ValueError: # not enough values to unpack (expected 2, got 1) + raise ValueError(f"invalid HTTP header line: {d(line)}") from None + if not _token_re.fullmatch(raw_name): + raise ValueError(f"invalid HTTP header name: {d(raw_name)}") + raw_value = raw_value.strip(b" \t") + if not _value_re.fullmatch(raw_value): + raise ValueError(f"invalid HTTP header value: {d(raw_value)}") + + name = raw_name.decode("ascii") # guaranteed to be ASCII at this point + value = raw_value.decode("ascii", "surrogateescape") + headers[name] = value + + else: + raise exceptions.SecurityError("too many HTTP headers") + + return headers + + +def parse_line( + read_line: Callable[[int], Generator[None, None, bytes]], +) -> Generator[None, None, bytes]: + """ + Parse a single line. + + CRLF is stripped from the return value. + + Args: + read_line: generator-based coroutine that reads a LF-terminated line + or raises an exception if there isn't enough data. + + Raises: + EOFError: if the connection is closed without a CRLF. + SecurityError: if the response exceeds a security limit. + + """ + try: + line = yield from read_line(MAX_LINE) + except RuntimeError: + raise exceptions.SecurityError("line too long") + # Not mandatory but safe - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.5 + if not line.endswith(b"\r\n"): + raise EOFError("line without CRLF") + return line[:-2] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/imports.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/imports.py new file mode 100644 index 00000000..a6a59d4c --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/imports.py @@ -0,0 +1,99 @@ +from __future__ import annotations + +import warnings +from typing import Any, Dict, Iterable, Optional + + +__all__ = ["lazy_import"] + + +def import_name(name: str, source: str, namespace: Dict[str, Any]) -> Any: + """ + Import ``name`` from ``source`` in ``namespace``. + + There are two use cases: + + - ``name`` is an object defined in ``source``; + - ``name`` is a submodule of ``source``. + + Neither :func:`__import__` nor :func:`~importlib.import_module` does + exactly this. :func:`__import__` is closer to the intended behavior. + + """ + level = 0 + while source[level] == ".": + level += 1 + assert level < len(source), "importing from parent isn't supported" + module = __import__(source[level:], namespace, None, [name], level) + return getattr(module, name) + + +def lazy_import( + namespace: Dict[str, Any], + aliases: Optional[Dict[str, str]] = None, + deprecated_aliases: Optional[Dict[str, str]] = None, +) -> None: + """ + Provide lazy, module-level imports. + + Typical use:: + + __getattr__, __dir__ = lazy_import( + globals(), + aliases={ + "": "", + ... + }, + deprecated_aliases={ + ..., + } + ) + + This function defines ``__getattr__`` and ``__dir__`` per :pep:`562`. + + """ + if aliases is None: + aliases = {} + if deprecated_aliases is None: + deprecated_aliases = {} + + namespace_set = set(namespace) + aliases_set = set(aliases) + deprecated_aliases_set = set(deprecated_aliases) + + assert not namespace_set & aliases_set, "namespace conflict" + assert not namespace_set & deprecated_aliases_set, "namespace conflict" + assert not aliases_set & deprecated_aliases_set, "namespace conflict" + + package = namespace["__name__"] + + def __getattr__(name: str) -> Any: + assert aliases is not None # mypy cannot figure this out + try: + source = aliases[name] + except KeyError: + pass + else: + return import_name(name, source, namespace) + + assert deprecated_aliases is not None # mypy cannot figure this out + try: + source = deprecated_aliases[name] + except KeyError: + pass + else: + warnings.warn( + f"{package}.{name} is deprecated", + DeprecationWarning, + stacklevel=2, + ) + return import_name(name, source, namespace) + + raise AttributeError(f"module {package!r} has no attribute {name!r}") + + namespace["__getattr__"] = __getattr__ + + def __dir__() -> Iterable[str]: + return sorted(namespace_set | aliases_set | deprecated_aliases_set) + + namespace["__dir__"] = __dir__ diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/auth.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/auth.py new file mode 100644 index 00000000..8825c14e --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/auth.py @@ -0,0 +1,188 @@ +from __future__ import annotations + +import functools +import hmac +import http +from typing import Any, Awaitable, Callable, Iterable, Optional, Tuple, Union, cast + +from ..datastructures import Headers +from ..exceptions import InvalidHeader +from ..headers import build_www_authenticate_basic, parse_authorization_basic +from .server import HTTPResponse, WebSocketServerProtocol + + +__all__ = ["BasicAuthWebSocketServerProtocol", "basic_auth_protocol_factory"] + +Credentials = Tuple[str, str] + + +def is_credentials(value: Any) -> bool: + try: + username, password = value + except (TypeError, ValueError): + return False + else: + return isinstance(username, str) and isinstance(password, str) + + +class BasicAuthWebSocketServerProtocol(WebSocketServerProtocol): + """ + WebSocket server protocol that enforces HTTP Basic Auth. + + """ + + realm: str = "" + """ + Scope of protection. + + If provided, it should contain only ASCII characters because the + encoding of non-ASCII characters is undefined. + """ + + username: Optional[str] = None + """Username of the authenticated user.""" + + def __init__( + self, + *args: Any, + realm: Optional[str] = None, + check_credentials: Optional[Callable[[str, str], Awaitable[bool]]] = None, + **kwargs: Any, + ) -> None: + if realm is not None: + self.realm = realm # shadow class attribute + self._check_credentials = check_credentials + super().__init__(*args, **kwargs) + + async def check_credentials(self, username: str, password: str) -> bool: + """ + Check whether credentials are authorized. + + This coroutine may be overridden in a subclass, for example to + authenticate against a database or an external service. + + Args: + username: HTTP Basic Auth username. + password: HTTP Basic Auth password. + + Returns: + bool: :obj:`True` if the handshake should continue; + :obj:`False` if it should fail with a HTTP 401 error. + + """ + if self._check_credentials is not None: + return await self._check_credentials(username, password) + + return False + + async def process_request( + self, + path: str, + request_headers: Headers, + ) -> Optional[HTTPResponse]: + """ + Check HTTP Basic Auth and return a HTTP 401 response if needed. + + """ + try: + authorization = request_headers["Authorization"] + except KeyError: + return ( + http.HTTPStatus.UNAUTHORIZED, + [("WWW-Authenticate", build_www_authenticate_basic(self.realm))], + b"Missing credentials\n", + ) + + try: + username, password = parse_authorization_basic(authorization) + except InvalidHeader: + return ( + http.HTTPStatus.UNAUTHORIZED, + [("WWW-Authenticate", build_www_authenticate_basic(self.realm))], + b"Unsupported credentials\n", + ) + + if not await self.check_credentials(username, password): + return ( + http.HTTPStatus.UNAUTHORIZED, + [("WWW-Authenticate", build_www_authenticate_basic(self.realm))], + b"Invalid credentials\n", + ) + + self.username = username + + return await super().process_request(path, request_headers) + + +def basic_auth_protocol_factory( + realm: Optional[str] = None, + credentials: Optional[Union[Credentials, Iterable[Credentials]]] = None, + check_credentials: Optional[Callable[[str, str], Awaitable[bool]]] = None, + create_protocol: Optional[Callable[[Any], BasicAuthWebSocketServerProtocol]] = None, +) -> Callable[[Any], BasicAuthWebSocketServerProtocol]: + """ + Protocol factory that enforces HTTP Basic Auth. + + :func:`basic_auth_protocol_factory` is designed to integrate with + :func:`~websockets.server.serve` like this:: + + websockets.serve( + ..., + create_protocol=websockets.basic_auth_protocol_factory( + realm="my dev server", + credentials=("hello", "iloveyou"), + ) + ) + + Args: + realm: indicates the scope of protection. It should contain only ASCII + characters because the encoding of non-ASCII characters is + undefined. Refer to section 2.2 of :rfc:`7235` for details. + credentials: defines hard coded authorized credentials. It can be a + ``(username, password)`` pair or a list of such pairs. + check_credentials: defines a coroutine that verifies credentials. + This coroutine receives ``username`` and ``password`` arguments + and returns a :class:`bool`. One of ``credentials`` or + ``check_credentials`` must be provided but not both. + create_protocol: factory that creates the protocol. By default, this + is :class:`BasicAuthWebSocketServerProtocol`. It can be replaced + by a subclass. + Raises: + TypeError: if the ``credentials`` or ``check_credentials`` argument is + wrong. + + """ + if (credentials is None) == (check_credentials is None): + raise TypeError("provide either credentials or check_credentials") + + if credentials is not None: + if is_credentials(credentials): + credentials_list = [cast(Credentials, credentials)] + elif isinstance(credentials, Iterable): + credentials_list = list(credentials) + if not all(is_credentials(item) for item in credentials_list): + raise TypeError(f"invalid credentials argument: {credentials}") + else: + raise TypeError(f"invalid credentials argument: {credentials}") + + credentials_dict = dict(credentials_list) + + async def check_credentials(username: str, password: str) -> bool: + try: + expected_password = credentials_dict[username] + except KeyError: + return False + return hmac.compare_digest(expected_password, password) + + if create_protocol is None: + # Not sure why mypy cannot figure this out. + create_protocol = cast( + Callable[[Any], BasicAuthWebSocketServerProtocol], + BasicAuthWebSocketServerProtocol, + ) + + return functools.partial( + create_protocol, + realm=realm, + check_credentials=check_credentials, + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/client.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/client.py new file mode 100644 index 00000000..fadc3efe --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/client.py @@ -0,0 +1,709 @@ +from __future__ import annotations + +import asyncio +import functools +import logging +import random +import urllib.parse +import warnings +from types import TracebackType +from typing import ( + Any, + AsyncIterator, + Callable, + Generator, + List, + Optional, + Sequence, + Tuple, + Type, + cast, +) + +from ..datastructures import Headers, HeadersLike +from ..exceptions import ( + InvalidHandshake, + InvalidHeader, + InvalidMessage, + InvalidStatusCode, + NegotiationError, + RedirectHandshake, + SecurityError, +) +from ..extensions import ClientExtensionFactory, Extension +from ..extensions.permessage_deflate import enable_client_permessage_deflate +from ..headers import ( + build_authorization_basic, + build_extension, + build_host, + build_subprotocol, + parse_extension, + parse_subprotocol, + validate_subprotocols, +) +from ..http import USER_AGENT +from ..typing import ExtensionHeader, LoggerLike, Origin, Subprotocol +from ..uri import WebSocketURI, parse_uri +from .handshake import build_request, check_response +from .http import read_response +from .protocol import WebSocketCommonProtocol + + +__all__ = ["connect", "unix_connect", "WebSocketClientProtocol"] + + +class WebSocketClientProtocol(WebSocketCommonProtocol): + """ + WebSocket client connection. + + :class:`WebSocketClientProtocol` provides :meth:`recv` and :meth:`send` + coroutines for receiving and sending messages. + + It supports asynchronous iteration to receive incoming messages:: + + async for message in websocket: + await process(message) + + The iterator exits normally when the connection is closed with close code + 1000 (OK) or 1001 (going away). It raises + a :exc:`~websockets.exceptions.ConnectionClosedError` when the connection + is closed with any other code. + + See :func:`connect` for the documentation of ``logger``, ``origin``, + ``extensions``, ``subprotocols``, and ``extra_headers``. + + See :class:`~websockets.legacy.protocol.WebSocketCommonProtocol` for the + documentation of ``ping_interval``, ``ping_timeout``, ``close_timeout``, + ``max_size``, ``max_queue``, ``read_limit``, and ``write_limit``. + + """ + + is_client = True + side = "client" + + def __init__( + self, + *, + logger: Optional[LoggerLike] = None, + origin: Optional[Origin] = None, + extensions: Optional[Sequence[ClientExtensionFactory]] = None, + subprotocols: Optional[Sequence[Subprotocol]] = None, + extra_headers: Optional[HeadersLike] = None, + **kwargs: Any, + ) -> None: + if logger is None: + logger = logging.getLogger("websockets.client") + super().__init__(logger=logger, **kwargs) + self.origin = origin + self.available_extensions = extensions + self.available_subprotocols = subprotocols + self.extra_headers = extra_headers + + def write_http_request(self, path: str, headers: Headers) -> None: + """ + Write request line and headers to the HTTP request. + + """ + self.path = path + self.request_headers = headers + + if self.debug: + self.logger.debug("> GET %s HTTP/1.1", path) + for key, value in headers.raw_items(): + self.logger.debug("> %s: %s", key, value) + + # Since the path and headers only contain ASCII characters, + # we can keep this simple. + request = f"GET {path} HTTP/1.1\r\n" + request += str(headers) + + self.transport.write(request.encode()) + + async def read_http_response(self) -> Tuple[int, Headers]: + """ + Read status line and headers from the HTTP response. + + If the response contains a body, it may be read from ``self.reader`` + after this coroutine returns. + + Raises: + InvalidMessage: if the HTTP message is malformed or isn't an + HTTP/1.1 GET response. + + """ + try: + status_code, reason, headers = await read_response(self.reader) + # Remove this branch when dropping support for Python < 3.8 + # because CancelledError no longer inherits Exception. + except asyncio.CancelledError: # pragma: no cover + raise + except Exception as exc: + raise InvalidMessage("did not receive a valid HTTP response") from exc + + if self.debug: + self.logger.debug("< HTTP/1.1 %d %s", status_code, reason) + for key, value in headers.raw_items(): + self.logger.debug("< %s: %s", key, value) + + self.response_headers = headers + + return status_code, self.response_headers + + @staticmethod + def process_extensions( + headers: Headers, + available_extensions: Optional[Sequence[ClientExtensionFactory]], + ) -> List[Extension]: + """ + Handle the Sec-WebSocket-Extensions HTTP response header. + + Check that each extension is supported, as well as its parameters. + + Return the list of accepted extensions. + + Raise :exc:`~websockets.exceptions.InvalidHandshake` to abort the + connection. + + :rfc:`6455` leaves the rules up to the specification of each + :extension. + + To provide this level of flexibility, for each extension accepted by + the server, we check for a match with each extension available in the + client configuration. If no match is found, an exception is raised. + + If several variants of the same extension are accepted by the server, + it may be configured several times, which won't make sense in general. + Extensions must implement their own requirements. For this purpose, + the list of previously accepted extensions is provided. + + Other requirements, for example related to mandatory extensions or the + order of extensions, may be implemented by overriding this method. + + """ + accepted_extensions: List[Extension] = [] + + header_values = headers.get_all("Sec-WebSocket-Extensions") + + if header_values: + + if available_extensions is None: + raise InvalidHandshake("no extensions supported") + + parsed_header_values: List[ExtensionHeader] = sum( + [parse_extension(header_value) for header_value in header_values], [] + ) + + for name, response_params in parsed_header_values: + + for extension_factory in available_extensions: + + # Skip non-matching extensions based on their name. + if extension_factory.name != name: + continue + + # Skip non-matching extensions based on their params. + try: + extension = extension_factory.process_response_params( + response_params, accepted_extensions + ) + except NegotiationError: + continue + + # Add matching extension to the final list. + accepted_extensions.append(extension) + + # Break out of the loop once we have a match. + break + + # If we didn't break from the loop, no extension in our list + # matched what the server sent. Fail the connection. + else: + raise NegotiationError( + f"Unsupported extension: " + f"name = {name}, params = {response_params}" + ) + + return accepted_extensions + + @staticmethod + def process_subprotocol( + headers: Headers, available_subprotocols: Optional[Sequence[Subprotocol]] + ) -> Optional[Subprotocol]: + """ + Handle the Sec-WebSocket-Protocol HTTP response header. + + Check that it contains exactly one supported subprotocol. + + Return the selected subprotocol. + + """ + subprotocol: Optional[Subprotocol] = None + + header_values = headers.get_all("Sec-WebSocket-Protocol") + + if header_values: + + if available_subprotocols is None: + raise InvalidHandshake("no subprotocols supported") + + parsed_header_values: Sequence[Subprotocol] = sum( + [parse_subprotocol(header_value) for header_value in header_values], [] + ) + + if len(parsed_header_values) > 1: + subprotocols = ", ".join(parsed_header_values) + raise InvalidHandshake(f"multiple subprotocols: {subprotocols}") + + subprotocol = parsed_header_values[0] + + if subprotocol not in available_subprotocols: + raise NegotiationError(f"unsupported subprotocol: {subprotocol}") + + return subprotocol + + async def handshake( + self, + wsuri: WebSocketURI, + origin: Optional[Origin] = None, + available_extensions: Optional[Sequence[ClientExtensionFactory]] = None, + available_subprotocols: Optional[Sequence[Subprotocol]] = None, + extra_headers: Optional[HeadersLike] = None, + ) -> None: + """ + Perform the client side of the opening handshake. + + Args: + wsuri: URI of the WebSocket server. + origin: value of the ``Origin`` header. + available_extensions: list of supported extensions, in order in + which they should be tried. + available_subprotocols: list of supported subprotocols, in order + of decreasing preference. + extra_headers: arbitrary HTTP headers to add to the request. + + Raises: + InvalidHandshake: if the handshake fails. + + """ + request_headers = Headers() + + request_headers["Host"] = build_host(wsuri.host, wsuri.port, wsuri.secure) + + if wsuri.user_info: + request_headers["Authorization"] = build_authorization_basic( + *wsuri.user_info + ) + + if origin is not None: + request_headers["Origin"] = origin + + key = build_request(request_headers) + + if available_extensions is not None: + extensions_header = build_extension( + [ + (extension_factory.name, extension_factory.get_request_params()) + for extension_factory in available_extensions + ] + ) + request_headers["Sec-WebSocket-Extensions"] = extensions_header + + if available_subprotocols is not None: + protocol_header = build_subprotocol(available_subprotocols) + request_headers["Sec-WebSocket-Protocol"] = protocol_header + + if self.extra_headers is not None: + request_headers.update(self.extra_headers) + + request_headers.setdefault("User-Agent", USER_AGENT) + + self.write_http_request(wsuri.resource_name, request_headers) + + status_code, response_headers = await self.read_http_response() + if status_code in (301, 302, 303, 307, 308): + if "Location" not in response_headers: + raise InvalidHeader("Location") + raise RedirectHandshake(response_headers["Location"]) + elif status_code != 101: + raise InvalidStatusCode(status_code, response_headers) + + check_response(response_headers, key) + + self.extensions = self.process_extensions( + response_headers, available_extensions + ) + + self.subprotocol = self.process_subprotocol( + response_headers, available_subprotocols + ) + + self.connection_open() + + +class Connect: + """ + Connect to the WebSocket server at ``uri``. + + Awaiting :func:`connect` yields a :class:`WebSocketClientProtocol` which + can then be used to send and receive messages. + + :func:`connect` can be used as a asynchronous context manager:: + + async with websockets.connect(...) as websocket: + ... + + The connection is closed automatically when exiting the context. + + :func:`connect` can be used as an infinite asynchronous iterator to + reconnect automatically on errors:: + + async for websocket in websockets.connect(...): + try: + ... + except websockets.ConnectionClosed: + continue + + The connection is closed automatically after each iteration of the loop. + + If an error occurs while establishing the connection, :func:`connect` + retries with exponential backoff. The backoff delay starts at three + seconds and increases up to one minute. + + If an error occurs in the body of the loop, you can handle the exception + and :func:`connect` will reconnect with the next iteration; or you can + let the exception bubble up and break out of the loop. This lets you + decide which errors trigger a reconnection and which errors are fatal. + + Args: + uri: URI of the WebSocket server. + create_protocol: factory for the :class:`asyncio.Protocol` managing + the connection; defaults to :class:`WebSocketClientProtocol`; may + be set to a wrapper or a subclass to customize connection handling. + logger: logger for this connection; + defaults to ``logging.getLogger("websockets.client")``; + see the :doc:`logging guide <../topics/logging>` for details. + compression: shortcut that enables the "permessage-deflate" extension + by default; may be set to :obj:`None` to disable compression; + see the :doc:`compression guide <../topics/compression>` for details. + origin: value of the ``Origin`` header. This is useful when connecting + to a server that validates the ``Origin`` header to defend against + Cross-Site WebSocket Hijacking attacks. + extensions: list of supported extensions, in order in which they + should be tried. + subprotocols: list of supported subprotocols, in order of decreasing + preference. + extra_headers: arbitrary HTTP headers to add to the request. + open_timeout: timeout for opening the connection in seconds; + :obj:`None` to disable the timeout + + See :class:`~websockets.legacy.protocol.WebSocketCommonProtocol` for the + documentation of ``ping_interval``, ``ping_timeout``, ``close_timeout``, + ``max_size``, ``max_queue``, ``read_limit``, and ``write_limit``. + + Any other keyword arguments are passed the event loop's + :meth:`~asyncio.loop.create_connection` method. + + For example: + + * You can set ``ssl`` to a :class:`~ssl.SSLContext` to enforce TLS + settings. When connecting to a ``wss://`` URI, if ``ssl`` isn't + provided, a TLS context is created + with :func:`~ssl.create_default_context`. + + * You can set ``host`` and ``port`` to connect to a different host and + port from those found in ``uri``. This only changes the destination of + the TCP connection. The host name from ``uri`` is still used in the TLS + handshake for secure connections and in the ``Host`` header. + + Returns: + WebSocketClientProtocol: WebSocket connection. + + Raises: + InvalidURI: if ``uri`` isn't a valid WebSocket URI. + InvalidHandshake: if the opening handshake fails. + ~asyncio.TimeoutError: if the opening handshake times out. + + """ + + MAX_REDIRECTS_ALLOWED = 10 + + def __init__( + self, + uri: str, + *, + create_protocol: Optional[Callable[[Any], WebSocketClientProtocol]] = None, + logger: Optional[LoggerLike] = None, + compression: Optional[str] = "deflate", + origin: Optional[Origin] = None, + extensions: Optional[Sequence[ClientExtensionFactory]] = None, + subprotocols: Optional[Sequence[Subprotocol]] = None, + extra_headers: Optional[HeadersLike] = None, + open_timeout: Optional[float] = 10, + ping_interval: Optional[float] = 20, + ping_timeout: Optional[float] = 20, + close_timeout: Optional[float] = None, + max_size: Optional[int] = 2**20, + max_queue: Optional[int] = 2**5, + read_limit: int = 2**16, + write_limit: int = 2**16, + **kwargs: Any, + ) -> None: + # Backwards compatibility: close_timeout used to be called timeout. + timeout: Optional[float] = kwargs.pop("timeout", None) + if timeout is None: + timeout = 10 + else: + warnings.warn("rename timeout to close_timeout", DeprecationWarning) + # If both are specified, timeout is ignored. + if close_timeout is None: + close_timeout = timeout + + # Backwards compatibility: create_protocol used to be called klass. + klass: Optional[Type[WebSocketClientProtocol]] = kwargs.pop("klass", None) + if klass is None: + klass = WebSocketClientProtocol + else: + warnings.warn("rename klass to create_protocol", DeprecationWarning) + # If both are specified, klass is ignored. + if create_protocol is None: + create_protocol = klass + + # Backwards compatibility: recv() used to return None on closed connections + legacy_recv: bool = kwargs.pop("legacy_recv", False) + + # Backwards compatibility: the loop parameter used to be supported. + _loop: Optional[asyncio.AbstractEventLoop] = kwargs.pop("loop", None) + if _loop is None: + loop = asyncio.get_event_loop() + else: + loop = _loop + warnings.warn("remove loop argument", DeprecationWarning) + + wsuri = parse_uri(uri) + if wsuri.secure: + kwargs.setdefault("ssl", True) + elif kwargs.get("ssl") is not None: + raise ValueError( + "connect() received a ssl argument for a ws:// URI, " + "use a wss:// URI to enable TLS" + ) + + if compression == "deflate": + extensions = enable_client_permessage_deflate(extensions) + elif compression is not None: + raise ValueError(f"unsupported compression: {compression}") + + if subprotocols is not None: + validate_subprotocols(subprotocols) + + factory = functools.partial( + create_protocol, + logger=logger, + origin=origin, + extensions=extensions, + subprotocols=subprotocols, + extra_headers=extra_headers, + ping_interval=ping_interval, + ping_timeout=ping_timeout, + close_timeout=close_timeout, + max_size=max_size, + max_queue=max_queue, + read_limit=read_limit, + write_limit=write_limit, + host=wsuri.host, + port=wsuri.port, + secure=wsuri.secure, + legacy_recv=legacy_recv, + loop=_loop, + ) + + if kwargs.pop("unix", False): + path: Optional[str] = kwargs.pop("path", None) + create_connection = functools.partial( + loop.create_unix_connection, factory, path, **kwargs + ) + else: + host: Optional[str] + port: Optional[int] + if kwargs.get("sock") is None: + host, port = wsuri.host, wsuri.port + else: + # If sock is given, host and port shouldn't be specified. + host, port = None, None + # If host and port are given, override values from the URI. + host = kwargs.pop("host", host) + port = kwargs.pop("port", port) + create_connection = functools.partial( + loop.create_connection, factory, host, port, **kwargs + ) + + self.open_timeout = open_timeout + if logger is None: + logger = logging.getLogger("websockets.client") + self.logger = logger + + # This is a coroutine function. + self._create_connection = create_connection + self._uri = uri + self._wsuri = wsuri + + def handle_redirect(self, uri: str) -> None: + # Update the state of this instance to connect to a new URI. + old_uri = self._uri + old_wsuri = self._wsuri + new_uri = urllib.parse.urljoin(old_uri, uri) + new_wsuri = parse_uri(new_uri) + + # Forbid TLS downgrade. + if old_wsuri.secure and not new_wsuri.secure: + raise SecurityError("redirect from WSS to WS") + + same_origin = ( + old_wsuri.host == new_wsuri.host and old_wsuri.port == new_wsuri.port + ) + + # Rewrite the host and port arguments for cross-origin redirects. + # This preserves connection overrides with the host and port + # arguments if the redirect points to the same host and port. + if not same_origin: + # Replace the host and port argument passed to the protocol factory. + factory = self._create_connection.args[0] + factory = functools.partial( + factory.func, + *factory.args, + **dict(factory.keywords, host=new_wsuri.host, port=new_wsuri.port), + ) + # Replace the host and port argument passed to create_connection. + self._create_connection = functools.partial( + self._create_connection.func, + *(factory, new_wsuri.host, new_wsuri.port), + **self._create_connection.keywords, + ) + + # Set the new WebSocket URI. This suffices for same-origin redirects. + self._uri = new_uri + self._wsuri = new_wsuri + + # async for ... in connect(...): + + BACKOFF_MIN = 1.92 + BACKOFF_MAX = 60.0 + BACKOFF_FACTOR = 1.618 + BACKOFF_INITIAL = 5 + + async def __aiter__(self) -> AsyncIterator[WebSocketClientProtocol]: + backoff_delay = self.BACKOFF_MIN + while True: + try: + async with self as protocol: + yield protocol + # Remove this branch when dropping support for Python < 3.8 + # because CancelledError no longer inherits Exception. + except asyncio.CancelledError: # pragma: no cover + raise + except Exception: + # Add a random initial delay between 0 and 5 seconds. + # See 7.2.3. Recovering from Abnormal Closure in RFC 6544. + if backoff_delay == self.BACKOFF_MIN: + initial_delay = random.random() * self.BACKOFF_INITIAL + self.logger.info( + "! connect failed; reconnecting in %.1f seconds", + initial_delay, + exc_info=True, + ) + await asyncio.sleep(initial_delay) + else: + self.logger.info( + "! connect failed again; retrying in %d seconds", + int(backoff_delay), + exc_info=True, + ) + await asyncio.sleep(int(backoff_delay)) + # Increase delay with truncated exponential backoff. + backoff_delay = backoff_delay * self.BACKOFF_FACTOR + backoff_delay = min(backoff_delay, self.BACKOFF_MAX) + continue + else: + # Connection succeeded - reset backoff delay + backoff_delay = self.BACKOFF_MIN + + # async with connect(...) as ...: + + async def __aenter__(self) -> WebSocketClientProtocol: + return await self + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: + await self.protocol.close() + + # ... = await connect(...) + + def __await__(self) -> Generator[Any, None, WebSocketClientProtocol]: + # Create a suitable iterator by calling __await__ on a coroutine. + return self.__await_impl_timeout__().__await__() + + async def __await_impl_timeout__(self) -> WebSocketClientProtocol: + return await asyncio.wait_for(self.__await_impl__(), self.open_timeout) + + async def __await_impl__(self) -> WebSocketClientProtocol: + for redirects in range(self.MAX_REDIRECTS_ALLOWED): + transport, protocol = await self._create_connection() + protocol = cast(WebSocketClientProtocol, protocol) + + try: + await protocol.handshake( + self._wsuri, + origin=protocol.origin, + available_extensions=protocol.available_extensions, + available_subprotocols=protocol.available_subprotocols, + extra_headers=protocol.extra_headers, + ) + except RedirectHandshake as exc: + protocol.fail_connection() + await protocol.wait_closed() + self.handle_redirect(exc.uri) + # Avoid leaking a connected socket when the handshake fails. + except (Exception, asyncio.CancelledError): + protocol.fail_connection() + await protocol.wait_closed() + raise + else: + self.protocol = protocol + return protocol + else: + raise SecurityError("too many redirects") + + # ... = yield from connect(...) - remove when dropping Python < 3.10 + + __iter__ = __await__ + + +connect = Connect + + +def unix_connect( + path: Optional[str] = None, + uri: str = "ws://localhost/", + **kwargs: Any, +) -> Connect: + """ + Similar to :func:`connect`, but for connecting to a Unix socket. + + This function builds upon the event loop's + :meth:`~asyncio.loop.create_unix_connection` method. + + It is only available on Unix. + + It's mainly useful for debugging servers listening on Unix sockets. + + Args: + path: file system path to the Unix socket. + uri: URI of the WebSocket server; the host is used in the TLS + handshake for secure connections and in the ``Host`` header. + + """ + return connect(uri=uri, path=path, unix=True, **kwargs) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/compatibility.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/compatibility.py new file mode 100644 index 00000000..df81de9d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/compatibility.py @@ -0,0 +1,13 @@ +from __future__ import annotations + +import asyncio +import sys +from typing import Any, Dict + + +def loop_if_py_lt_38(loop: asyncio.AbstractEventLoop) -> Dict[str, Any]: + """ + Helper for the removal of the loop argument in Python 3.10. + + """ + return {"loop": loop} if sys.version_info[:2] < (3, 8) else {} diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/framing.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/framing.py new file mode 100644 index 00000000..c4de7eb2 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/framing.py @@ -0,0 +1,174 @@ +from __future__ import annotations + +import dataclasses +import struct +from typing import Any, Awaitable, Callable, NamedTuple, Optional, Sequence, Tuple + +from .. import extensions, frames +from ..exceptions import PayloadTooBig, ProtocolError + + +try: + from ..speedups import apply_mask +except ImportError: # pragma: no cover + from ..utils import apply_mask + + +class Frame(NamedTuple): + + fin: bool + opcode: frames.Opcode + data: bytes + rsv1: bool = False + rsv2: bool = False + rsv3: bool = False + + @property + def new_frame(self) -> frames.Frame: + return frames.Frame( + self.opcode, + self.data, + self.fin, + self.rsv1, + self.rsv2, + self.rsv3, + ) + + def __str__(self) -> str: + return str(self.new_frame) + + def check(self) -> None: + return self.new_frame.check() + + @classmethod + async def read( + cls, + reader: Callable[[int], Awaitable[bytes]], + *, + mask: bool, + max_size: Optional[int] = None, + extensions: Optional[Sequence[extensions.Extension]] = None, + ) -> Frame: + """ + Read a WebSocket frame. + + Args: + reader: coroutine that reads exactly the requested number of + bytes, unless the end of file is reached. + mask: whether the frame should be masked i.e. whether the read + happens on the server side. + max_size: maximum payload size in bytes. + extensions: list of extensions, applied in reverse order. + + Raises: + PayloadTooBig: if the frame exceeds ``max_size``. + ProtocolError: if the frame contains incorrect values. + + """ + + # Read the header. + data = await reader(2) + head1, head2 = struct.unpack("!BB", data) + + # While not Pythonic, this is marginally faster than calling bool(). + fin = True if head1 & 0b10000000 else False + rsv1 = True if head1 & 0b01000000 else False + rsv2 = True if head1 & 0b00100000 else False + rsv3 = True if head1 & 0b00010000 else False + + try: + opcode = frames.Opcode(head1 & 0b00001111) + except ValueError as exc: + raise ProtocolError("invalid opcode") from exc + + if (True if head2 & 0b10000000 else False) != mask: + raise ProtocolError("incorrect masking") + + length = head2 & 0b01111111 + if length == 126: + data = await reader(2) + (length,) = struct.unpack("!H", data) + elif length == 127: + data = await reader(8) + (length,) = struct.unpack("!Q", data) + if max_size is not None and length > max_size: + raise PayloadTooBig(f"over size limit ({length} > {max_size} bytes)") + if mask: + mask_bits = await reader(4) + + # Read the data. + data = await reader(length) + if mask: + data = apply_mask(data, mask_bits) + + new_frame = frames.Frame(opcode, data, fin, rsv1, rsv2, rsv3) + + if extensions is None: + extensions = [] + for extension in reversed(extensions): + new_frame = extension.decode(new_frame, max_size=max_size) + + new_frame.check() + + return cls( + new_frame.fin, + new_frame.opcode, + new_frame.data, + new_frame.rsv1, + new_frame.rsv2, + new_frame.rsv3, + ) + + def write( + self, + write: Callable[[bytes], Any], + *, + mask: bool, + extensions: Optional[Sequence[extensions.Extension]] = None, + ) -> None: + """ + Write a WebSocket frame. + + Args: + frame: frame to write. + write: function that writes bytes. + mask: whether the frame should be masked i.e. whether the write + happens on the client side. + extensions: list of extensions, applied in order. + + Raises: + ProtocolError: if the frame contains incorrect values. + + """ + # The frame is written in a single call to write in order to prevent + # TCP fragmentation. See #68 for details. This also makes it safe to + # send frames concurrently from multiple coroutines. + write(self.new_frame.serialize(mask=mask, extensions=extensions)) + + +# Backwards compatibility with previously documented public APIs + +from ..frames import Close, prepare_ctrl as encode_data, prepare_data # noqa + + +def parse_close(data: bytes) -> Tuple[int, str]: + """ + Parse the payload from a close frame. + + Returns: + Tuple[int, str]: close code and reason. + + Raises: + ProtocolError: if data is ill-formed. + UnicodeDecodeError: if the reason isn't valid UTF-8. + + """ + return dataclasses.astuple(Close.parse(data)) # type: ignore + + +def serialize_close(code: int, reason: str) -> bytes: + """ + Serialize the payload for a close frame. + + """ + return Close(code, reason).serialize() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/handshake.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/handshake.py new file mode 100644 index 00000000..569937bb --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/handshake.py @@ -0,0 +1,165 @@ +from __future__ import annotations + +import base64 +import binascii +from typing import List + +from ..datastructures import Headers, MultipleValuesError +from ..exceptions import InvalidHeader, InvalidHeaderValue, InvalidUpgrade +from ..headers import parse_connection, parse_upgrade +from ..typing import ConnectionOption, UpgradeProtocol +from ..utils import accept_key as accept, generate_key + + +__all__ = ["build_request", "check_request", "build_response", "check_response"] + + +def build_request(headers: Headers) -> str: + """ + Build a handshake request to send to the server. + + Update request headers passed in argument. + + Args: + headers: handshake request headers. + + Returns: + str: ``key`` that must be passed to :func:`check_response`. + + """ + key = generate_key() + headers["Upgrade"] = "websocket" + headers["Connection"] = "Upgrade" + headers["Sec-WebSocket-Key"] = key + headers["Sec-WebSocket-Version"] = "13" + return key + + +def check_request(headers: Headers) -> str: + """ + Check a handshake request received from the client. + + This function doesn't verify that the request is an HTTP/1.1 or higher GET + request and doesn't perform ``Host`` and ``Origin`` checks. These controls + are usually performed earlier in the HTTP request handling code. They're + the responsibility of the caller. + + Args: + headers: handshake request headers. + + Returns: + str: ``key`` that must be passed to :func:`build_response`. + + Raises: + InvalidHandshake: if the handshake request is invalid; + then the server must return 400 Bad Request error. + + """ + connection: List[ConnectionOption] = sum( + [parse_connection(value) for value in headers.get_all("Connection")], [] + ) + + if not any(value.lower() == "upgrade" for value in connection): + raise InvalidUpgrade("Connection", ", ".join(connection)) + + upgrade: List[UpgradeProtocol] = sum( + [parse_upgrade(value) for value in headers.get_all("Upgrade")], [] + ) + + # For compatibility with non-strict implementations, ignore case when + # checking the Upgrade header. The RFC always uses "websocket", except + # in section 11.2. (IANA registration) where it uses "WebSocket". + if not (len(upgrade) == 1 and upgrade[0].lower() == "websocket"): + raise InvalidUpgrade("Upgrade", ", ".join(upgrade)) + + try: + s_w_key = headers["Sec-WebSocket-Key"] + except KeyError as exc: + raise InvalidHeader("Sec-WebSocket-Key") from exc + except MultipleValuesError as exc: + raise InvalidHeader( + "Sec-WebSocket-Key", "more than one Sec-WebSocket-Key header found" + ) from exc + + try: + raw_key = base64.b64decode(s_w_key.encode(), validate=True) + except binascii.Error as exc: + raise InvalidHeaderValue("Sec-WebSocket-Key", s_w_key) from exc + if len(raw_key) != 16: + raise InvalidHeaderValue("Sec-WebSocket-Key", s_w_key) + + try: + s_w_version = headers["Sec-WebSocket-Version"] + except KeyError as exc: + raise InvalidHeader("Sec-WebSocket-Version") from exc + except MultipleValuesError as exc: + raise InvalidHeader( + "Sec-WebSocket-Version", "more than one Sec-WebSocket-Version header found" + ) from exc + + if s_w_version != "13": + raise InvalidHeaderValue("Sec-WebSocket-Version", s_w_version) + + return s_w_key + + +def build_response(headers: Headers, key: str) -> None: + """ + Build a handshake response to send to the client. + + Update response headers passed in argument. + + Args: + headers: handshake response headers. + key: returned by :func:`check_request`. + + """ + headers["Upgrade"] = "websocket" + headers["Connection"] = "Upgrade" + headers["Sec-WebSocket-Accept"] = accept(key) + + +def check_response(headers: Headers, key: str) -> None: + """ + Check a handshake response received from the server. + + This function doesn't verify that the response is an HTTP/1.1 or higher + response with a 101 status code. These controls are the responsibility of + the caller. + + Args: + headers: handshake response headers. + key: returned by :func:`build_request`. + + Raises: + InvalidHandshake: if the handshake response is invalid. + + """ + connection: List[ConnectionOption] = sum( + [parse_connection(value) for value in headers.get_all("Connection")], [] + ) + + if not any(value.lower() == "upgrade" for value in connection): + raise InvalidUpgrade("Connection", " ".join(connection)) + + upgrade: List[UpgradeProtocol] = sum( + [parse_upgrade(value) for value in headers.get_all("Upgrade")], [] + ) + + # For compatibility with non-strict implementations, ignore case when + # checking the Upgrade header. The RFC always uses "websocket", except + # in section 11.2. (IANA registration) where it uses "WebSocket". + if not (len(upgrade) == 1 and upgrade[0].lower() == "websocket"): + raise InvalidUpgrade("Upgrade", ", ".join(upgrade)) + + try: + s_w_accept = headers["Sec-WebSocket-Accept"] + except KeyError as exc: + raise InvalidHeader("Sec-WebSocket-Accept") from exc + except MultipleValuesError as exc: + raise InvalidHeader( + "Sec-WebSocket-Accept", "more than one Sec-WebSocket-Accept header found" + ) from exc + + if s_w_accept != accept(key): + raise InvalidHeaderValue("Sec-WebSocket-Accept", s_w_accept) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/http.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/http.py new file mode 100644 index 00000000..cc2ef1f0 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/http.py @@ -0,0 +1,201 @@ +from __future__ import annotations + +import asyncio +import re +from typing import Tuple + +from ..datastructures import Headers +from ..exceptions import SecurityError + + +__all__ = ["read_request", "read_response"] + +MAX_HEADERS = 256 +MAX_LINE = 4110 + + +def d(value: bytes) -> str: + """ + Decode a bytestring for interpolating into an error message. + + """ + return value.decode(errors="backslashreplace") + + +# See https://www.rfc-editor.org/rfc/rfc7230.html#appendix-B. + +# Regex for validating header names. + +_token_re = re.compile(rb"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+") + +# Regex for validating header values. + +# We don't attempt to support obsolete line folding. + +# Include HTAB (\x09), SP (\x20), VCHAR (\x21-\x7e), obs-text (\x80-\xff). + +# The ABNF is complicated because it attempts to express that optional +# whitespace is ignored. We strip whitespace and don't revalidate that. + +# See also https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189 + +_value_re = re.compile(rb"[\x09\x20-\x7e\x80-\xff]*") + + +async def read_request(stream: asyncio.StreamReader) -> Tuple[str, Headers]: + """ + Read an HTTP/1.1 GET request and return ``(path, headers)``. + + ``path`` isn't URL-decoded or validated in any way. + + ``path`` and ``headers`` are expected to contain only ASCII characters. + Other characters are represented with surrogate escapes. + + :func:`read_request` doesn't attempt to read the request body because + WebSocket handshake requests don't have one. If the request contains a + body, it may be read from ``stream`` after this coroutine returns. + + Args: + stream: input to read the request from + + Raises: + EOFError: if the connection is closed without a full HTTP request + SecurityError: if the request exceeds a security limit + ValueError: if the request isn't well formatted + + """ + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.1 + + # Parsing is simple because fixed values are expected for method and + # version and because path isn't checked. Since WebSocket software tends + # to implement HTTP/1.1 strictly, there's little need for lenient parsing. + + try: + request_line = await read_line(stream) + except EOFError as exc: + raise EOFError("connection closed while reading HTTP request line") from exc + + try: + method, raw_path, version = request_line.split(b" ", 2) + except ValueError: # not enough values to unpack (expected 3, got 1-2) + raise ValueError(f"invalid HTTP request line: {d(request_line)}") from None + + if method != b"GET": + raise ValueError(f"unsupported HTTP method: {d(method)}") + if version != b"HTTP/1.1": + raise ValueError(f"unsupported HTTP version: {d(version)}") + path = raw_path.decode("ascii", "surrogateescape") + + headers = await read_headers(stream) + + return path, headers + + +async def read_response(stream: asyncio.StreamReader) -> Tuple[int, str, Headers]: + """ + Read an HTTP/1.1 response and return ``(status_code, reason, headers)``. + + ``reason`` and ``headers`` are expected to contain only ASCII characters. + Other characters are represented with surrogate escapes. + + :func:`read_request` doesn't attempt to read the response body because + WebSocket handshake responses don't have one. If the response contains a + body, it may be read from ``stream`` after this coroutine returns. + + Args: + stream: input to read the response from + + Raises: + EOFError: if the connection is closed without a full HTTP response + SecurityError: if the response exceeds a security limit + ValueError: if the response isn't well formatted + + """ + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.2 + + # As in read_request, parsing is simple because a fixed value is expected + # for version, status_code is a 3-digit number, and reason can be ignored. + + try: + status_line = await read_line(stream) + except EOFError as exc: + raise EOFError("connection closed while reading HTTP status line") from exc + + try: + version, raw_status_code, raw_reason = status_line.split(b" ", 2) + except ValueError: # not enough values to unpack (expected 3, got 1-2) + raise ValueError(f"invalid HTTP status line: {d(status_line)}") from None + + if version != b"HTTP/1.1": + raise ValueError(f"unsupported HTTP version: {d(version)}") + try: + status_code = int(raw_status_code) + except ValueError: # invalid literal for int() with base 10 + raise ValueError(f"invalid HTTP status code: {d(raw_status_code)}") from None + if not 100 <= status_code < 1000: + raise ValueError(f"unsupported HTTP status code: {d(raw_status_code)}") + if not _value_re.fullmatch(raw_reason): + raise ValueError(f"invalid HTTP reason phrase: {d(raw_reason)}") + reason = raw_reason.decode() + + headers = await read_headers(stream) + + return status_code, reason, headers + + +async def read_headers(stream: asyncio.StreamReader) -> Headers: + """ + Read HTTP headers from ``stream``. + + Non-ASCII characters are represented with surrogate escapes. + + """ + # https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2 + + # We don't attempt to support obsolete line folding. + + headers = Headers() + for _ in range(MAX_HEADERS + 1): + try: + line = await read_line(stream) + except EOFError as exc: + raise EOFError("connection closed while reading HTTP headers") from exc + if line == b"": + break + + try: + raw_name, raw_value = line.split(b":", 1) + except ValueError: # not enough values to unpack (expected 2, got 1) + raise ValueError(f"invalid HTTP header line: {d(line)}") from None + if not _token_re.fullmatch(raw_name): + raise ValueError(f"invalid HTTP header name: {d(raw_name)}") + raw_value = raw_value.strip(b" \t") + if not _value_re.fullmatch(raw_value): + raise ValueError(f"invalid HTTP header value: {d(raw_value)}") + + name = raw_name.decode("ascii") # guaranteed to be ASCII at this point + value = raw_value.decode("ascii", "surrogateescape") + headers[name] = value + + else: + raise SecurityError("too many HTTP headers") + + return headers + + +async def read_line(stream: asyncio.StreamReader) -> bytes: + """ + Read a single line from ``stream``. + + CRLF is stripped from the return value. + + """ + # Security: this is bounded by the StreamReader's limit (default = 32 KiB). + line = await stream.readline() + # Security: this guarantees header values are small (hard-coded = 4 KiB) + if len(line) > MAX_LINE: + raise SecurityError("line too long") + # Not mandatory but safe - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.5 + if not line.endswith(b"\r\n"): + raise EOFError("line without CRLF") + return line[:-2] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/protocol.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/protocol.py new file mode 100644 index 00000000..d1d52bfa --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/protocol.py @@ -0,0 +1,1605 @@ +from __future__ import annotations + +import asyncio +import codecs +import collections +import logging +import random +import ssl +import struct +import uuid +import warnings +from typing import ( + Any, + AsyncIterable, + AsyncIterator, + Awaitable, + Deque, + Dict, + Iterable, + List, + Mapping, + Optional, + Union, + cast, +) + +from ..connection import State +from ..datastructures import Headers +from ..exceptions import ( + ConnectionClosed, + ConnectionClosedError, + ConnectionClosedOK, + InvalidState, + PayloadTooBig, + ProtocolError, +) +from ..extensions import Extension +from ..frames import ( + OK_CLOSE_CODES, + OP_BINARY, + OP_CLOSE, + OP_CONT, + OP_PING, + OP_PONG, + OP_TEXT, + Close, + Opcode, + prepare_ctrl, + prepare_data, +) +from ..typing import Data, LoggerLike, Subprotocol +from .compatibility import loop_if_py_lt_38 +from .framing import Frame + + +__all__ = ["WebSocketCommonProtocol", "broadcast"] + + +# In order to ensure consistency, the code always checks the current value of +# WebSocketCommonProtocol.state before assigning a new value and never yields +# between the check and the assignment. + + +class WebSocketCommonProtocol(asyncio.Protocol): + """ + WebSocket connection. + + :class:`WebSocketCommonProtocol` provides APIs shared between WebSocket + servers and clients. You shouldn't use it directly. Instead, use + :class:`~websockets.client.WebSocketClientProtocol` or + :class:`~websockets.server.WebSocketServerProtocol`. + + This documentation focuses on low-level details that aren't covered in the + documentation of :class:`~websockets.client.WebSocketClientProtocol` and + :class:`~websockets.server.WebSocketServerProtocol` for the sake of + simplicity. + + Once the connection is open, a Ping_ frame is sent every ``ping_interval`` + seconds. This serves as a keepalive. It helps keeping the connection + open, especially in the presence of proxies with short timeouts on + inactive connections. Set ``ping_interval`` to :obj:`None` to disable + this behavior. + + .. _Ping: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.5.2 + + If the corresponding Pong_ frame isn't received within ``ping_timeout`` + seconds, the connection is considered unusable and is closed with code + 1011. This ensures that the remote endpoint remains responsive. Set + ``ping_timeout`` to :obj:`None` to disable this behavior. + + .. _Pong: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.5.3 + + The ``close_timeout`` parameter defines a maximum wait time for completing + the closing handshake and terminating the TCP connection. For legacy + reasons, :meth:`close` completes in at most ``5 * close_timeout`` seconds + for clients and ``4 * close_timeout`` for servers. + + See the discussion of :doc:`timeouts <../topics/timeouts>` for details. + + ``close_timeout`` needs to be a parameter of the protocol because + websockets usually calls :meth:`close` implicitly upon exit: + + * on the client side, when :func:`~websockets.client.connect` is used as a + context manager; + * on the server side, when the connection handler terminates; + + To apply a timeout to any other API, wrap it in :func:`~asyncio.wait_for`. + + The ``max_size`` parameter enforces the maximum size for incoming messages + in bytes. The default value is 1 MiB. If a larger message is received, + :meth:`recv` will raise :exc:`~websockets.exceptions.ConnectionClosedError` + and the connection will be closed with code 1009. + + The ``max_queue`` parameter sets the maximum length of the queue that + holds incoming messages. The default value is ``32``. Messages are added + to an in-memory queue when they're received; then :meth:`recv` pops from + that queue. In order to prevent excessive memory consumption when + messages are received faster than they can be processed, the queue must + be bounded. If the queue fills up, the protocol stops processing incoming + data until :meth:`recv` is called. In this situation, various receive + buffers (at least in :mod:`asyncio` and in the OS) will fill up, then the + TCP receive window will shrink, slowing down transmission to avoid packet + loss. + + Since Python can use up to 4 bytes of memory to represent a single + character, each connection may use up to ``4 * max_size * max_queue`` + bytes of memory to store incoming messages. By default, this is 128 MiB. + You may want to lower the limits, depending on your application's + requirements. + + The ``read_limit`` argument sets the high-water limit of the buffer for + incoming bytes. The low-water limit is half the high-water limit. The + default value is 64 KiB, half of asyncio's default (based on the current + implementation of :class:`~asyncio.StreamReader`). + + The ``write_limit`` argument sets the high-water limit of the buffer for + outgoing bytes. The low-water limit is a quarter of the high-water limit. + The default value is 64 KiB, equal to asyncio's default (based on the + current implementation of ``FlowControlMixin``). + + See the discussion of :doc:`memory usage <../topics/memory>` for details. + + Args: + logger: logger for this connection; + defaults to ``logging.getLogger("websockets.protocol")``; + see the :doc:`logging guide <../topics/logging>` for details. + ping_interval: delay between keepalive pings in seconds; + :obj:`None` to disable keepalive pings. + ping_timeout: timeout for keepalive pings in seconds; + :obj:`None` to disable timeouts. + close_timeout: timeout for closing the connection in seconds; + for legacy reasons, the actual timeout is 4 or 5 times larger. + max_size: maximum size of incoming messages in bytes; + :obj:`None` to disable the limit. + max_queue: maximum number of incoming messages in receive buffer; + :obj:`None` to disable the limit. + read_limit: high-water mark of read buffer in bytes. + write_limit: high-water mark of write buffer in bytes. + + """ + + # There are only two differences between the client-side and server-side + # behavior: masking the payload and closing the underlying TCP connection. + # Set is_client = True/False and side = "client"/"server" to pick a side. + is_client: bool + side: str = "undefined" + + def __init__( + self, + *, + logger: Optional[LoggerLike] = None, + ping_interval: Optional[float] = 20, + ping_timeout: Optional[float] = 20, + close_timeout: Optional[float] = None, + max_size: Optional[int] = 2**20, + max_queue: Optional[int] = 2**5, + read_limit: int = 2**16, + write_limit: int = 2**16, + # The following arguments are kept only for backwards compatibility. + host: Optional[str] = None, + port: Optional[int] = None, + secure: Optional[bool] = None, + legacy_recv: bool = False, + loop: Optional[asyncio.AbstractEventLoop] = None, + timeout: Optional[float] = None, + ) -> None: + if legacy_recv: # pragma: no cover + warnings.warn("legacy_recv is deprecated", DeprecationWarning) + + # Backwards compatibility: close_timeout used to be called timeout. + if timeout is None: + timeout = 10 + else: + warnings.warn("rename timeout to close_timeout", DeprecationWarning) + # If both are specified, timeout is ignored. + if close_timeout is None: + close_timeout = timeout + + # Backwards compatibility: the loop parameter used to be supported. + if loop is None: + loop = asyncio.get_event_loop() + else: + warnings.warn("remove loop argument", DeprecationWarning) + + self.ping_interval = ping_interval + self.ping_timeout = ping_timeout + self.close_timeout = close_timeout + self.max_size = max_size + self.max_queue = max_queue + self.read_limit = read_limit + self.write_limit = write_limit + + # Unique identifier. For logs. + self.id: uuid.UUID = uuid.uuid4() + """Unique identifier of the connection. Useful in logs.""" + + # Logger or LoggerAdapter for this connection. + if logger is None: + logger = logging.getLogger("websockets.protocol") + # https://github.com/python/typeshed/issues/5561 + logger = cast(logging.Logger, logger) + self.logger: LoggerLike = logging.LoggerAdapter(logger, {"websocket": self}) + """Logger for this connection.""" + + # Track if DEBUG is enabled. Shortcut logging calls if it isn't. + self.debug = logger.isEnabledFor(logging.DEBUG) + + self.loop = loop + + self._host = host + self._port = port + self._secure = secure + self.legacy_recv = legacy_recv + + # Configure read buffer limits. The high-water limit is defined by + # ``self.read_limit``. The ``limit`` argument controls the line length + # limit and half the buffer limit of :class:`~asyncio.StreamReader`. + # That's why it must be set to half of ``self.read_limit``. + self.reader = asyncio.StreamReader(limit=read_limit // 2, loop=loop) + + # Copied from asyncio.FlowControlMixin + self._paused = False + self._drain_waiter: Optional[asyncio.Future[None]] = None + + self._drain_lock = asyncio.Lock(**loop_if_py_lt_38(loop)) + + # This class implements the data transfer and closing handshake, which + # are shared between the client-side and the server-side. + # Subclasses implement the opening handshake and, on success, execute + # :meth:`connection_open` to change the state to OPEN. + self.state = State.CONNECTING + if self.debug: + self.logger.debug("= connection is CONNECTING") + + # HTTP protocol parameters. + self.path: str + """Path of the opening handshake request.""" + self.request_headers: Headers + """Opening handshake request headers.""" + self.response_headers: Headers + """Opening handshake response headers.""" + + # WebSocket protocol parameters. + self.extensions: List[Extension] = [] + self.subprotocol: Optional[Subprotocol] = None + """Subprotocol, if one was negotiated.""" + + # Close code and reason, set when a close frame is sent or received. + self.close_rcvd: Optional[Close] = None + self.close_sent: Optional[Close] = None + self.close_rcvd_then_sent: Optional[bool] = None + + # Completed when the connection state becomes CLOSED. Translates the + # :meth:`connection_lost` callback to a :class:`~asyncio.Future` + # that can be awaited. (Other :class:`~asyncio.Protocol` callbacks are + # translated by ``self.stream_reader``). + self.connection_lost_waiter: asyncio.Future[None] = loop.create_future() + + # Queue of received messages. + self.messages: Deque[Data] = collections.deque() + self._pop_message_waiter: Optional[asyncio.Future[None]] = None + self._put_message_waiter: Optional[asyncio.Future[None]] = None + + # Protect sending fragmented messages. + self._fragmented_message_waiter: Optional[asyncio.Future[None]] = None + + # Mapping of ping IDs to pong waiters, in chronological order. + self.pings: Dict[bytes, asyncio.Future[None]] = {} + + # Task running the data transfer. + self.transfer_data_task: asyncio.Task[None] + + # Exception that occurred during data transfer, if any. + self.transfer_data_exc: Optional[BaseException] = None + + # Task sending keepalive pings. + self.keepalive_ping_task: asyncio.Task[None] + + # Task closing the TCP connection. + self.close_connection_task: asyncio.Task[None] + + # Copied from asyncio.FlowControlMixin + async def _drain_helper(self) -> None: # pragma: no cover + if self.connection_lost_waiter.done(): + raise ConnectionResetError("Connection lost") + if not self._paused: + return + waiter = self._drain_waiter + assert waiter is None or waiter.cancelled() + waiter = self.loop.create_future() + self._drain_waiter = waiter + await waiter + + # Copied from asyncio.StreamWriter + async def _drain(self) -> None: # pragma: no cover + if self.reader is not None: + exc = self.reader.exception() + if exc is not None: + raise exc + if self.transport is not None: + if self.transport.is_closing(): + # Yield to the event loop so connection_lost() may be + # called. Without this, _drain_helper() would return + # immediately, and code that calls + # write(...); yield from drain() + # in a loop would never call connection_lost(), so it + # would not see an error when the socket is closed. + await asyncio.sleep(0, **loop_if_py_lt_38(self.loop)) + await self._drain_helper() + + def connection_open(self) -> None: + """ + Callback when the WebSocket opening handshake completes. + + Enter the OPEN state and start the data transfer phase. + + """ + # 4.1. The WebSocket Connection is Established. + assert self.state is State.CONNECTING + self.state = State.OPEN + if self.debug: + self.logger.debug("= connection is OPEN") + # Start the task that receives incoming WebSocket messages. + self.transfer_data_task = self.loop.create_task(self.transfer_data()) + # Start the task that sends pings at regular intervals. + self.keepalive_ping_task = self.loop.create_task(self.keepalive_ping()) + # Start the task that eventually closes the TCP connection. + self.close_connection_task = self.loop.create_task(self.close_connection()) + + @property + def host(self) -> Optional[str]: + alternative = "remote_address" if self.is_client else "local_address" + warnings.warn(f"use {alternative}[0] instead of host", DeprecationWarning) + return self._host + + @property + def port(self) -> Optional[int]: + alternative = "remote_address" if self.is_client else "local_address" + warnings.warn(f"use {alternative}[1] instead of port", DeprecationWarning) + return self._port + + @property + def secure(self) -> Optional[bool]: + warnings.warn("don't use secure", DeprecationWarning) + return self._secure + + # Public API + + @property + def local_address(self) -> Any: + """ + Local address of the connection. + + For IPv4 connections, this is a ``(host, port)`` tuple. + + The format of the address depends on the address family; + see :meth:`~socket.socket.getsockname`. + + :obj:`None` if the TCP connection isn't established yet. + + """ + try: + transport = self.transport + except AttributeError: + return None + else: + return transport.get_extra_info("sockname") + + @property + def remote_address(self) -> Any: + """ + Remote address of the connection. + + For IPv4 connections, this is a ``(host, port)`` tuple. + + The format of the address depends on the address family; + see :meth:`~socket.socket.getpeername`. + + :obj:`None` if the TCP connection isn't established yet. + + """ + try: + transport = self.transport + except AttributeError: + return None + else: + return transport.get_extra_info("peername") + + @property + def open(self) -> bool: + """ + :obj:`True` when the connection is open; :obj:`False` otherwise. + + This attribute may be used to detect disconnections. However, this + approach is discouraged per the EAFP_ principle. Instead, you should + handle :exc:`~websockets.exceptions.ConnectionClosed` exceptions. + + .. _EAFP: https://docs.python.org/3/glossary.html#term-eafp + + """ + return self.state is State.OPEN and not self.transfer_data_task.done() + + @property + def closed(self) -> bool: + """ + :obj:`True` when the connection is closed; :obj:`False` otherwise. + + Be aware that both :attr:`open` and :attr:`closed` are :obj:`False` + during the opening and closing sequences. + + """ + return self.state is State.CLOSED + + @property + def close_code(self) -> Optional[int]: + """ + WebSocket close code, defined in `section 7.1.5 of RFC 6455`_. + + .. _section 7.1.5 of RFC 6455: + https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.5 + + :obj:`None` if the connection isn't closed yet. + + """ + if self.state is not State.CLOSED: + return None + elif self.close_rcvd is None: + return 1006 + else: + return self.close_rcvd.code + + @property + def close_reason(self) -> Optional[str]: + """ + WebSocket close reason, defined in `section 7.1.6 of RFC 6455`_. + + .. _section 7.1.6 of RFC 6455: + https://www.rfc-editor.org/rfc/rfc6455.html#section-7.1.6 + + :obj:`None` if the connection isn't closed yet. + + """ + if self.state is not State.CLOSED: + return None + elif self.close_rcvd is None: + return "" + else: + return self.close_rcvd.reason + + async def __aiter__(self) -> AsyncIterator[Data]: + """ + Iterate on incoming messages. + + The iterator exits normally when the connection is closed with the + close code 1000 (OK) or 1001(going away). It raises + a :exc:`~websockets.exceptions.ConnectionClosedError` exception when + the connection is closed with any other code. + + """ + try: + while True: + yield await self.recv() + except ConnectionClosedOK: + return + + async def recv(self) -> Data: + """ + Receive the next message. + + When the connection is closed, :meth:`recv` raises + :exc:`~websockets.exceptions.ConnectionClosed`. Specifically, it + raises :exc:`~websockets.exceptions.ConnectionClosedOK` after a normal + connection closure and + :exc:`~websockets.exceptions.ConnectionClosedError` after a protocol + error or a network failure. This is how you detect the end of the + message stream. + + Canceling :meth:`recv` is safe. There's no risk of losing the next + message. The next invocation of :meth:`recv` will return it. + + This makes it possible to enforce a timeout by wrapping :meth:`recv` + in :func:`~asyncio.wait_for`. + + Returns: + Data: A string (:class:`str`) for a Text_ frame. A bytestring + (:class:`bytes`) for a Binary_ frame. + + .. _Text: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 + .. _Binary: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 + + Raises: + ConnectionClosed: when the connection is closed. + RuntimeError: if two coroutines call :meth:`recv` concurrently. + + """ + if self._pop_message_waiter is not None: + raise RuntimeError( + "cannot call recv while another coroutine " + "is already waiting for the next message" + ) + + # Don't await self.ensure_open() here: + # - messages could be available in the queue even if the connection + # is closed; + # - messages could be received before the closing frame even if the + # connection is closing. + + # Wait until there's a message in the queue (if necessary) or the + # connection is closed. + while len(self.messages) <= 0: + pop_message_waiter: asyncio.Future[None] = self.loop.create_future() + self._pop_message_waiter = pop_message_waiter + try: + # If asyncio.wait() is canceled, it doesn't cancel + # pop_message_waiter and self.transfer_data_task. + await asyncio.wait( + [pop_message_waiter, self.transfer_data_task], + return_when=asyncio.FIRST_COMPLETED, + **loop_if_py_lt_38(self.loop), + ) + finally: + self._pop_message_waiter = None + + # If asyncio.wait(...) exited because self.transfer_data_task + # completed before receiving a new message, raise a suitable + # exception (or return None if legacy_recv is enabled). + if not pop_message_waiter.done(): + if self.legacy_recv: + return None # type: ignore + else: + # Wait until the connection is closed to raise + # ConnectionClosed with the correct code and reason. + await self.ensure_open() + + # Pop a message from the queue. + message = self.messages.popleft() + + # Notify transfer_data(). + if self._put_message_waiter is not None: + self._put_message_waiter.set_result(None) + self._put_message_waiter = None + + return message + + async def send( + self, + message: Union[Data, Iterable[Data], AsyncIterable[Data]], + ) -> None: + """ + Send a message. + + A string (:class:`str`) is sent as a Text_ frame. A bytestring or + bytes-like object (:class:`bytes`, :class:`bytearray`, or + :class:`memoryview`) is sent as a Binary_ frame. + + .. _Text: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 + .. _Binary: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 + + :meth:`send` also accepts an iterable or an asynchronous iterable of + strings, bytestrings, or bytes-like objects to enable fragmentation_. + Each item is treated as a message fragment and sent in its own frame. + All items must be of the same type, or else :meth:`send` will raise a + :exc:`TypeError` and the connection will be closed. + + .. _fragmentation: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.4 + + :meth:`send` rejects dict-like objects because this is often an error. + (If you want to send the keys of a dict-like object as fragments, call + its :meth:`~dict.keys` method and pass the result to :meth:`send`.) + + Canceling :meth:`send` is discouraged. Instead, you should close the + connection with :meth:`close`. Indeed, there are only two situations + where :meth:`send` may yield control to the event loop and then get + canceled; in both cases, :meth:`close` has the same effect and is + more clear: + + 1. The write buffer is full. If you don't want to wait until enough + data is sent, your only alternative is to close the connection. + :meth:`close` will likely time out then abort the TCP connection. + 2. ``message`` is an asynchronous iterator that yields control. + Stopping in the middle of a fragmented message will cause a + protocol error and the connection will be closed. + + When the connection is closed, :meth:`send` raises + :exc:`~websockets.exceptions.ConnectionClosed`. Specifically, it + raises :exc:`~websockets.exceptions.ConnectionClosedOK` after a normal + connection closure and + :exc:`~websockets.exceptions.ConnectionClosedError` after a protocol + error or a network failure. + + Args: + message (Union[Data, Iterable[Data], AsyncIterable[Data]): message + to send. + + Raises: + ConnectionClosed: when the connection is closed. + TypeError: if ``message`` doesn't have a supported type. + + """ + await self.ensure_open() + + # While sending a fragmented message, prevent sending other messages + # until all fragments are sent. + while self._fragmented_message_waiter is not None: + await asyncio.shield(self._fragmented_message_waiter) + + # Unfragmented message -- this case must be handled first because + # strings and bytes-like objects are iterable. + + if isinstance(message, (str, bytes, bytearray, memoryview)): + opcode, data = prepare_data(message) + await self.write_frame(True, opcode, data) + + # Catch a common mistake -- passing a dict to send(). + + elif isinstance(message, Mapping): + raise TypeError("data is a dict-like object") + + # Fragmented message -- regular iterator. + + elif isinstance(message, Iterable): + + # Work around https://github.com/python/mypy/issues/6227 + message = cast(Iterable[Data], message) + + iter_message = iter(message) + try: + message_chunk = next(iter_message) + except StopIteration: + return + opcode, data = prepare_data(message_chunk) + + self._fragmented_message_waiter = asyncio.Future() + try: + # First fragment. + await self.write_frame(False, opcode, data) + + # Other fragments. + for message_chunk in iter_message: + confirm_opcode, data = prepare_data(message_chunk) + if confirm_opcode != opcode: + raise TypeError("data contains inconsistent types") + await self.write_frame(False, OP_CONT, data) + + # Final fragment. + await self.write_frame(True, OP_CONT, b"") + + except (Exception, asyncio.CancelledError): + # We're half-way through a fragmented message and we can't + # complete it. This makes the connection unusable. + self.fail_connection(1011) + raise + + finally: + self._fragmented_message_waiter.set_result(None) + self._fragmented_message_waiter = None + + # Fragmented message -- asynchronous iterator + + elif isinstance(message, AsyncIterable): + # aiter_message = aiter(message) without aiter + # https://github.com/python/mypy/issues/5738 + aiter_message = type(message).__aiter__(message) # type: ignore + try: + # message_chunk = anext(aiter_message) without anext + # https://github.com/python/mypy/issues/5738 + message_chunk = await type(aiter_message).__anext__( # type: ignore + aiter_message + ) + except StopAsyncIteration: + return + opcode, data = prepare_data(message_chunk) + + self._fragmented_message_waiter = asyncio.Future() + try: + # First fragment. + await self.write_frame(False, opcode, data) + + # Other fragments. + # https://github.com/python/mypy/issues/5738 + # coverage reports this code as not covered, but it is + # exercised by tests - changing it breaks the tests! + async for message_chunk in aiter_message: # type: ignore # pragma: no cover # noqa + confirm_opcode, data = prepare_data(message_chunk) + if confirm_opcode != opcode: + raise TypeError("data contains inconsistent types") + await self.write_frame(False, OP_CONT, data) + + # Final fragment. + await self.write_frame(True, OP_CONT, b"") + + except (Exception, asyncio.CancelledError): + # We're half-way through a fragmented message and we can't + # complete it. This makes the connection unusable. + self.fail_connection(1011) + raise + + finally: + self._fragmented_message_waiter.set_result(None) + self._fragmented_message_waiter = None + + else: + raise TypeError("data must be str, bytes-like, or iterable") + + async def close(self, code: int = 1000, reason: str = "") -> None: + """ + Perform the closing handshake. + + :meth:`close` waits for the other end to complete the handshake and + for the TCP connection to terminate. As a consequence, there's no need + to await :meth:`wait_closed` after :meth:`close`. + + :meth:`close` is idempotent: it doesn't do anything once the + connection is closed. + + Wrapping :func:`close` in :func:`~asyncio.create_task` is safe, given + that errors during connection termination aren't particularly useful. + + Canceling :meth:`close` is discouraged. If it takes too long, you can + set a shorter ``close_timeout``. If you don't want to wait, let the + Python process exit, then the OS will take care of closing the TCP + connection. + + Args: + code: WebSocket close code. + reason: WebSocket close reason. + + """ + try: + await asyncio.wait_for( + self.write_close_frame(Close(code, reason)), + self.close_timeout, + **loop_if_py_lt_38(self.loop), + ) + except asyncio.TimeoutError: + # If the close frame cannot be sent because the send buffers + # are full, the closing handshake won't complete anyway. + # Fail the connection to shut down faster. + self.fail_connection() + + # If no close frame is received within the timeout, wait_for() cancels + # the data transfer task and raises TimeoutError. + + # If close() is called multiple times concurrently and one of these + # calls hits the timeout, the data transfer task will be canceled. + # Other calls will receive a CancelledError here. + + try: + # If close() is canceled during the wait, self.transfer_data_task + # is canceled before the timeout elapses. + await asyncio.wait_for( + self.transfer_data_task, + self.close_timeout, + **loop_if_py_lt_38(self.loop), + ) + except (asyncio.TimeoutError, asyncio.CancelledError): + pass + + # Wait for the close connection task to close the TCP connection. + await asyncio.shield(self.close_connection_task) + + async def wait_closed(self) -> None: + """ + Wait until the connection is closed. + + This coroutine is identical to the :attr:`closed` attribute, except it + can be awaited. + + This can make it easier to detect connection termination, regardless + of its cause, in tasks that interact with the WebSocket connection. + + """ + await asyncio.shield(self.connection_lost_waiter) + + async def ping(self, data: Optional[Data] = None) -> Awaitable[None]: + """ + Send a Ping_. + + .. _Ping: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.5.2 + + A ping may serve as a keepalive or as a check that the remote endpoint + received all messages up to this point + + Canceling :meth:`ping` is discouraged. If :meth:`ping` doesn't return + immediately, it means the write buffer is full. If you don't want to + wait, you should close the connection. + + Canceling the :class:`~asyncio.Future` returned by :meth:`ping` has no + effect. + + Args: + data (Optional[Data]): payload of the ping; a string will be + encoded to UTF-8; or :obj:`None` to generate a payload + containing four random bytes. + + Returns: + ~asyncio.Future: A future that will be completed when the + corresponding pong is received. You can ignore it if you + don't intend to wait. + + :: + + pong_waiter = await ws.ping() + await pong_waiter # only if you want to wait for the pong + + Raises: + ConnectionClosed: when the connection is closed. + RuntimeError: if another ping was sent with the same data and + the corresponding pong wasn't received yet. + + """ + await self.ensure_open() + + if data is not None: + data = prepare_ctrl(data) + + # Protect against duplicates if a payload is explicitly set. + if data in self.pings: + raise RuntimeError("already waiting for a pong with the same data") + + # Generate a unique random payload otherwise. + while data is None or data in self.pings: + data = struct.pack("!I", random.getrandbits(32)) + + self.pings[data] = self.loop.create_future() + + await self.write_frame(True, OP_PING, data) + + return asyncio.shield(self.pings[data]) + + async def pong(self, data: Data = b"") -> None: + """ + Send a Pong_. + + .. _Pong: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.5.3 + + An unsolicited pong may serve as a unidirectional heartbeat. + + Canceling :meth:`pong` is discouraged. If :meth:`pong` doesn't return + immediately, it means the write buffer is full. If you don't want to + wait, you should close the connection. + + Args: + data (Data): payload of the pong; a string will be encoded to + UTF-8. + + Raises: + ConnectionClosed: when the connection is closed. + + """ + await self.ensure_open() + + data = prepare_ctrl(data) + + await self.write_frame(True, OP_PONG, data) + + # Private methods - no guarantees. + + def connection_closed_exc(self) -> ConnectionClosed: + exc: ConnectionClosed + if ( + self.close_rcvd is not None + and self.close_rcvd.code in OK_CLOSE_CODES + and self.close_sent is not None + and self.close_sent.code in OK_CLOSE_CODES + ): + exc = ConnectionClosedOK( + self.close_rcvd, + self.close_sent, + self.close_rcvd_then_sent, + ) + else: + exc = ConnectionClosedError( + self.close_rcvd, + self.close_sent, + self.close_rcvd_then_sent, + ) + # Chain to the exception that terminated data transfer, if any. + exc.__cause__ = self.transfer_data_exc + return exc + + async def ensure_open(self) -> None: + """ + Check that the WebSocket connection is open. + + Raise :exc:`~websockets.exceptions.ConnectionClosed` if it isn't. + + """ + # Handle cases from most common to least common for performance. + if self.state is State.OPEN: + # If self.transfer_data_task exited without a closing handshake, + # self.close_connection_task may be closing the connection, going + # straight from OPEN to CLOSED. + if self.transfer_data_task.done(): + await asyncio.shield(self.close_connection_task) + raise self.connection_closed_exc() + else: + return + + if self.state is State.CLOSED: + raise self.connection_closed_exc() + + if self.state is State.CLOSING: + # If we started the closing handshake, wait for its completion to + # get the proper close code and reason. self.close_connection_task + # will complete within 4 or 5 * close_timeout after close(). The + # CLOSING state also occurs when failing the connection. In that + # case self.close_connection_task will complete even faster. + await asyncio.shield(self.close_connection_task) + raise self.connection_closed_exc() + + # Control may only reach this point in buggy third-party subclasses. + assert self.state is State.CONNECTING + raise InvalidState("WebSocket connection isn't established yet") + + async def transfer_data(self) -> None: + """ + Read incoming messages and put them in a queue. + + This coroutine runs in a task until the closing handshake is started. + + """ + try: + while True: + message = await self.read_message() + + # Exit the loop when receiving a close frame. + if message is None: + break + + # Wait until there's room in the queue (if necessary). + if self.max_queue is not None: + while len(self.messages) >= self.max_queue: + self._put_message_waiter = self.loop.create_future() + try: + await asyncio.shield(self._put_message_waiter) + finally: + self._put_message_waiter = None + + # Put the message in the queue. + self.messages.append(message) + + # Notify recv(). + if self._pop_message_waiter is not None: + self._pop_message_waiter.set_result(None) + self._pop_message_waiter = None + + except asyncio.CancelledError as exc: + self.transfer_data_exc = exc + # If fail_connection() cancels this task, avoid logging the error + # twice and failing the connection again. + raise + + except ProtocolError as exc: + self.transfer_data_exc = exc + self.fail_connection(1002) + + except (ConnectionError, TimeoutError, EOFError, ssl.SSLError) as exc: + # Reading data with self.reader.readexactly may raise: + # - most subclasses of ConnectionError if the TCP connection + # breaks, is reset, or is aborted; + # - TimeoutError if the TCP connection times out; + # - IncompleteReadError, a subclass of EOFError, if fewer + # bytes are available than requested; + # - ssl.SSLError if the other side infringes the TLS protocol. + self.transfer_data_exc = exc + self.fail_connection(1006) + + except UnicodeDecodeError as exc: + self.transfer_data_exc = exc + self.fail_connection(1007) + + except PayloadTooBig as exc: + self.transfer_data_exc = exc + self.fail_connection(1009) + + except Exception as exc: + # This shouldn't happen often because exceptions expected under + # regular circumstances are handled above. If it does, consider + # catching and handling more exceptions. + self.logger.error("data transfer failed", exc_info=True) + + self.transfer_data_exc = exc + self.fail_connection(1011) + + async def read_message(self) -> Optional[Data]: + """ + Read a single message from the connection. + + Re-assemble data frames if the message is fragmented. + + Return :obj:`None` when the closing handshake is started. + + """ + frame = await self.read_data_frame(max_size=self.max_size) + + # A close frame was received. + if frame is None: + return None + + if frame.opcode == OP_TEXT: + text = True + elif frame.opcode == OP_BINARY: + text = False + else: # frame.opcode == OP_CONT + raise ProtocolError("unexpected opcode") + + # Shortcut for the common case - no fragmentation + if frame.fin: + return frame.data.decode("utf-8") if text else frame.data + + # 5.4. Fragmentation + chunks: List[Data] = [] + max_size = self.max_size + if text: + decoder_factory = codecs.getincrementaldecoder("utf-8") + decoder = decoder_factory(errors="strict") + if max_size is None: + + def append(frame: Frame) -> None: + nonlocal chunks + chunks.append(decoder.decode(frame.data, frame.fin)) + + else: + + def append(frame: Frame) -> None: + nonlocal chunks, max_size + chunks.append(decoder.decode(frame.data, frame.fin)) + assert isinstance(max_size, int) + max_size -= len(frame.data) + + else: + if max_size is None: + + def append(frame: Frame) -> None: + nonlocal chunks + chunks.append(frame.data) + + else: + + def append(frame: Frame) -> None: + nonlocal chunks, max_size + chunks.append(frame.data) + assert isinstance(max_size, int) + max_size -= len(frame.data) + + append(frame) + + while not frame.fin: + frame = await self.read_data_frame(max_size=max_size) + if frame is None: + raise ProtocolError("incomplete fragmented message") + if frame.opcode != OP_CONT: + raise ProtocolError("unexpected opcode") + append(frame) + + return ("" if text else b"").join(chunks) + + async def read_data_frame(self, max_size: Optional[int]) -> Optional[Frame]: + """ + Read a single data frame from the connection. + + Process control frames received before the next data frame. + + Return :obj:`None` if a close frame is encountered before any data frame. + + """ + # 6.2. Receiving Data + while True: + frame = await self.read_frame(max_size) + + # 5.5. Control Frames + if frame.opcode == OP_CLOSE: + # 7.1.5. The WebSocket Connection Close Code + # 7.1.6. The WebSocket Connection Close Reason + self.close_rcvd = Close.parse(frame.data) + if self.close_sent is not None: + self.close_rcvd_then_sent = False + try: + # Echo the original data instead of re-serializing it with + # Close.serialize() because that fails when the close frame + # is empty and Close.parse() synthetizes a 1005 close code. + await self.write_close_frame(self.close_rcvd, frame.data) + except ConnectionClosed: + # Connection closed before we could echo the close frame. + pass + return None + + elif frame.opcode == OP_PING: + # Answer pings, unless connection is CLOSING. + if self.state is State.OPEN: + try: + await self.pong(frame.data) + except ConnectionClosed: + # Connection closed while draining write buffer. + pass + + elif frame.opcode == OP_PONG: + if frame.data in self.pings: + # Sending a pong for only the most recent ping is legal. + # Acknowledge all previous pings too in that case. + ping_id = None + ping_ids = [] + for ping_id, ping in self.pings.items(): + ping_ids.append(ping_id) + if not ping.done(): + ping.set_result(None) + if ping_id == frame.data: + break + else: # pragma: no cover + assert False, "ping_id is in self.pings" + # Remove acknowledged pings from self.pings. + for ping_id in ping_ids: + del self.pings[ping_id] + + # 5.6. Data Frames + else: + return frame + + async def read_frame(self, max_size: Optional[int]) -> Frame: + """ + Read a single frame from the connection. + + """ + frame = await Frame.read( + self.reader.readexactly, + mask=not self.is_client, + max_size=max_size, + extensions=self.extensions, + ) + if self.debug: + self.logger.debug("< %s", frame) + return frame + + def write_frame_sync(self, fin: bool, opcode: int, data: bytes) -> None: + frame = Frame(fin, Opcode(opcode), data) + if self.debug: + self.logger.debug("> %s", frame) + frame.write( + self.transport.write, + mask=self.is_client, + extensions=self.extensions, + ) + + async def drain(self) -> None: + try: + # drain() cannot be called concurrently by multiple coroutines: + # http://bugs.python.org/issue29930. Remove this lock when no + # version of Python where this bugs exists is supported anymore. + async with self._drain_lock: + # Handle flow control automatically. + await self._drain() + except ConnectionError: + # Terminate the connection if the socket died. + self.fail_connection() + # Wait until the connection is closed to raise ConnectionClosed + # with the correct code and reason. + await self.ensure_open() + + async def write_frame( + self, fin: bool, opcode: int, data: bytes, *, _state: int = State.OPEN + ) -> None: + # Defensive assertion for protocol compliance. + if self.state is not _state: # pragma: no cover + raise InvalidState( + f"Cannot write to a WebSocket in the {self.state.name} state" + ) + self.write_frame_sync(fin, opcode, data) + await self.drain() + + async def write_close_frame( + self, close: Close, data: Optional[bytes] = None + ) -> None: + """ + Write a close frame if and only if the connection state is OPEN. + + This dedicated coroutine must be used for writing close frames to + ensure that at most one close frame is sent on a given connection. + + """ + # Test and set the connection state before sending the close frame to + # avoid sending two frames in case of concurrent calls. + if self.state is State.OPEN: + # 7.1.3. The WebSocket Closing Handshake is Started + self.state = State.CLOSING + if self.debug: + self.logger.debug("= connection is CLOSING") + + self.close_sent = close + if self.close_rcvd is not None: + self.close_rcvd_then_sent = True + if data is None: + data = close.serialize() + + # 7.1.2. Start the WebSocket Closing Handshake + await self.write_frame(True, OP_CLOSE, data, _state=State.CLOSING) + + async def keepalive_ping(self) -> None: + """ + Send a Ping frame and wait for a Pong frame at regular intervals. + + This coroutine exits when the connection terminates and one of the + following happens: + + - :meth:`ping` raises :exc:`ConnectionClosed`, or + - :meth:`close_connection` cancels :attr:`keepalive_ping_task`. + + """ + if self.ping_interval is None: + return + + try: + while True: + await asyncio.sleep( + self.ping_interval, + **loop_if_py_lt_38(self.loop), + ) + + # ping() raises CancelledError if the connection is closed, + # when close_connection() cancels self.keepalive_ping_task. + + # ping() raises ConnectionClosed if the connection is lost, + # when connection_lost() calls abort_pings(). + + self.logger.debug("% sending keepalive ping") + pong_waiter = await self.ping() + + if self.ping_timeout is not None: + try: + await asyncio.wait_for( + pong_waiter, + self.ping_timeout, + **loop_if_py_lt_38(self.loop), + ) + self.logger.debug("% received keepalive pong") + except asyncio.TimeoutError: + if self.debug: + self.logger.debug("! timed out waiting for keepalive pong") + self.fail_connection(1011, "keepalive ping timeout") + break + + # Remove this branch when dropping support for Python < 3.8 + # because CancelledError no longer inherits Exception. + except asyncio.CancelledError: + raise + + except ConnectionClosed: + pass + + except Exception: + self.logger.error("keepalive ping failed", exc_info=True) + + async def close_connection(self) -> None: + """ + 7.1.1. Close the WebSocket Connection + + When the opening handshake succeeds, :meth:`connection_open` starts + this coroutine in a task. It waits for the data transfer phase to + complete then it closes the TCP connection cleanly. + + When the opening handshake fails, :meth:`fail_connection` does the + same. There's no data transfer phase in that case. + + """ + try: + # Wait for the data transfer phase to complete. + if hasattr(self, "transfer_data_task"): + try: + await self.transfer_data_task + except asyncio.CancelledError: + pass + + # Cancel the keepalive ping task. + if hasattr(self, "keepalive_ping_task"): + self.keepalive_ping_task.cancel() + + # A client should wait for a TCP close from the server. + if self.is_client and hasattr(self, "transfer_data_task"): + if await self.wait_for_connection_lost(): + # Coverage marks this line as a partially executed branch. + # I supect a bug in coverage. Ignore it for now. + return # pragma: no cover + if self.debug: + self.logger.debug("! timed out waiting for TCP close") + + # Half-close the TCP connection if possible (when there's no TLS). + if self.transport.can_write_eof(): + if self.debug: + self.logger.debug("x half-closing TCP connection") + # write_eof() doesn't document which exceptions it raises. + # "[Errno 107] Transport endpoint is not connected" happens + # but it isn't completely clear under which circumstances. + # uvloop can raise RuntimeError here. + try: + self.transport.write_eof() + except (OSError, RuntimeError): # pragma: no cover + pass + + if await self.wait_for_connection_lost(): + # Coverage marks this line as a partially executed branch. + # I supect a bug in coverage. Ignore it for now. + return # pragma: no cover + if self.debug: + self.logger.debug("! timed out waiting for TCP close") + + finally: + # The try/finally ensures that the transport never remains open, + # even if this coroutine is canceled (for example). + await self.close_transport() + + async def close_transport(self) -> None: + """ + Close the TCP connection. + + """ + # If connection_lost() was called, the TCP connection is closed. + # However, if TLS is enabled, the transport still needs closing. + # Else asyncio complains: ResourceWarning: unclosed transport. + if self.connection_lost_waiter.done() and self.transport.is_closing(): + return + + # Close the TCP connection. Buffers are flushed asynchronously. + if self.debug: + self.logger.debug("x closing TCP connection") + self.transport.close() + + if await self.wait_for_connection_lost(): + return + if self.debug: + self.logger.debug("! timed out waiting for TCP close") + + # Abort the TCP connection. Buffers are discarded. + if self.debug: + self.logger.debug("x aborting TCP connection") + self.transport.abort() + + # connection_lost() is called quickly after aborting. + # Coverage marks this line as a partially executed branch. + # I supect a bug in coverage. Ignore it for now. + await self.wait_for_connection_lost() # pragma: no cover + + async def wait_for_connection_lost(self) -> bool: + """ + Wait until the TCP connection is closed or ``self.close_timeout`` elapses. + + Return :obj:`True` if the connection is closed and :obj:`False` + otherwise. + + """ + if not self.connection_lost_waiter.done(): + try: + await asyncio.wait_for( + asyncio.shield(self.connection_lost_waiter), + self.close_timeout, + **loop_if_py_lt_38(self.loop), + ) + except asyncio.TimeoutError: + pass + # Re-check self.connection_lost_waiter.done() synchronously because + # connection_lost() could run between the moment the timeout occurs + # and the moment this coroutine resumes running. + return self.connection_lost_waiter.done() + + def fail_connection(self, code: int = 1006, reason: str = "") -> None: + """ + 7.1.7. Fail the WebSocket Connection + + This requires: + + 1. Stopping all processing of incoming data, which means cancelling + :attr:`transfer_data_task`. The close code will be 1006 unless a + close frame was received earlier. + + 2. Sending a close frame with an appropriate code if the opening + handshake succeeded and the other side is likely to process it. + + 3. Closing the connection. :meth:`close_connection` takes care of + this once :attr:`transfer_data_task` exits after being canceled. + + (The specification describes these steps in the opposite order.) + + """ + if self.debug: + self.logger.debug("! failing connection with code %d", code) + + # Cancel transfer_data_task if the opening handshake succeeded. + # cancel() is idempotent and ignored if the task is done already. + if hasattr(self, "transfer_data_task"): + self.transfer_data_task.cancel() + + # Send a close frame when the state is OPEN (a close frame was already + # sent if it's CLOSING), except when failing the connection because of + # an error reading from or writing to the network. + # Don't send a close frame if the connection is broken. + if code != 1006 and self.state is State.OPEN: + close = Close(code, reason) + + # Write the close frame without draining the write buffer. + + # Keeping fail_connection() synchronous guarantees it can't + # get stuck and simplifies the implementation of the callers. + # Not drainig the write buffer is acceptable in this context. + + # This duplicates a few lines of code from write_close_frame(). + + self.state = State.CLOSING + if self.debug: + self.logger.debug("= connection is CLOSING") + + # If self.close_rcvd was set, the connection state would be + # CLOSING. Therefore self.close_rcvd isn't set and we don't + # have to set self.close_rcvd_then_sent. + assert self.close_rcvd is None + self.close_sent = close + + self.write_frame_sync(True, OP_CLOSE, close.serialize()) + + # Start close_connection_task if the opening handshake didn't succeed. + if not hasattr(self, "close_connection_task"): + self.close_connection_task = self.loop.create_task(self.close_connection()) + + def abort_pings(self) -> None: + """ + Raise ConnectionClosed in pending keepalive pings. + + They'll never receive a pong once the connection is closed. + + """ + assert self.state is State.CLOSED + exc = self.connection_closed_exc() + + for ping in self.pings.values(): + ping.set_exception(exc) + # If the exception is never retrieved, it will be logged when ping + # is garbage-collected. This is confusing for users. + # Given that ping is done (with an exception), canceling it does + # nothing, but it prevents logging the exception. + ping.cancel() + + # asyncio.Protocol methods + + def connection_made(self, transport: asyncio.BaseTransport) -> None: + """ + Configure write buffer limits. + + The high-water limit is defined by ``self.write_limit``. + + The low-water limit currently defaults to ``self.write_limit // 4`` in + :meth:`~asyncio.WriteTransport.set_write_buffer_limits`, which should + be all right for reasonable use cases of this library. + + This is the earliest point where we can get hold of the transport, + which means it's the best point for configuring it. + + """ + transport = cast(asyncio.Transport, transport) + transport.set_write_buffer_limits(self.write_limit) + self.transport = transport + + # Copied from asyncio.StreamReaderProtocol + self.reader.set_transport(transport) + + def connection_lost(self, exc: Optional[Exception]) -> None: + """ + 7.1.4. The WebSocket Connection is Closed. + + """ + self.state = State.CLOSED + self.logger.debug("= connection is CLOSED") + + self.abort_pings() + + # If self.connection_lost_waiter isn't pending, that's a bug, because: + # - it's set only here in connection_lost() which is called only once; + # - it must never be canceled. + self.connection_lost_waiter.set_result(None) + + if True: # pragma: no cover + + # Copied from asyncio.StreamReaderProtocol + if self.reader is not None: + if exc is None: + self.reader.feed_eof() + else: + self.reader.set_exception(exc) + + # Copied from asyncio.FlowControlMixin + # Wake up the writer if currently paused. + if not self._paused: + return + waiter = self._drain_waiter + if waiter is None: + return + self._drain_waiter = None + if waiter.done(): + return + if exc is None: + waiter.set_result(None) + else: + waiter.set_exception(exc) + + def pause_writing(self) -> None: # pragma: no cover + assert not self._paused + self._paused = True + + def resume_writing(self) -> None: # pragma: no cover + assert self._paused + self._paused = False + + waiter = self._drain_waiter + if waiter is not None: + self._drain_waiter = None + if not waiter.done(): + waiter.set_result(None) + + def data_received(self, data: bytes) -> None: + self.reader.feed_data(data) + + def eof_received(self) -> None: + """ + Close the transport after receiving EOF. + + The WebSocket protocol has its own closing handshake: endpoints close + the TCP or TLS connection after sending and receiving a close frame. + + As a consequence, they never need to write after receiving EOF, so + there's no reason to keep the transport open by returning :obj:`True`. + + Besides, that doesn't work on TLS connections. + + """ + self.reader.feed_eof() + + +def broadcast(websockets: Iterable[WebSocketCommonProtocol], message: Data) -> None: + """ + Broadcast a message to several WebSocket connections. + + A string (:class:`str`) is sent as a Text_ frame. A bytestring or + bytes-like object (:class:`bytes`, :class:`bytearray`, or + :class:`memoryview`) is sent as a Binary_ frame. + + .. _Text: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 + .. _Binary: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 + + :func:`broadcast` pushes the message synchronously to all connections even + if their write buffers are overflowing. There's no backpressure. + + :func:`broadcast` skips silently connections that aren't open in order to + avoid errors on connections where the closing handshake is in progress. + + If you broadcast messages faster than a connection can handle them, + messages will pile up in its write buffer until the connection times out. + Keep low values for ``ping_interval`` and ``ping_timeout`` to prevent + excessive memory usage by slow connections when you use :func:`broadcast`. + + Unlike :meth:`~websockets.server.WebSocketServerProtocol.send`, + :func:`broadcast` doesn't support sending fragmented messages. Indeed, + fragmentation is useful for sending large messages without buffering + them in memory, while :func:`broadcast` buffers one copy per connection + as fast as possible. + + Args: + websockets (Iterable[WebSocketCommonProtocol]): WebSocket connections + to which the message will be sent. + message (Data): message to send. + + Raises: + RuntimeError: if a connection is busy sending a fragmented message. + TypeError: if ``message`` doesn't have a supported type. + + """ + if not isinstance(message, (str, bytes, bytearray, memoryview)): + raise TypeError("data must be str or bytes-like") + + opcode, data = prepare_data(message) + + for websocket in websockets: + if websocket.state is not State.OPEN: + continue + + if websocket._fragmented_message_waiter is not None: + raise RuntimeError("busy sending a fragmented message") + + websocket.write_frame_sync(True, opcode, data) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/server.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/server.py new file mode 100644 index 00000000..3e51db1b --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/legacy/server.py @@ -0,0 +1,1156 @@ +from __future__ import annotations + +import asyncio +import email.utils +import functools +import http +import inspect +import logging +import socket +import warnings +from types import TracebackType +from typing import ( + Any, + Awaitable, + Callable, + Generator, + Iterable, + List, + Optional, + Sequence, + Set, + Tuple, + Type, + Union, + cast, +) + +from ..connection import State +from ..datastructures import Headers, HeadersLike, MultipleValuesError +from ..exceptions import ( + AbortHandshake, + InvalidHandshake, + InvalidHeader, + InvalidMessage, + InvalidOrigin, + InvalidUpgrade, + NegotiationError, +) +from ..extensions import Extension, ServerExtensionFactory +from ..extensions.permessage_deflate import enable_server_permessage_deflate +from ..headers import ( + build_extension, + parse_extension, + parse_subprotocol, + validate_subprotocols, +) +from ..http import USER_AGENT +from ..typing import ExtensionHeader, LoggerLike, Origin, Subprotocol +from .compatibility import loop_if_py_lt_38 +from .handshake import build_response, check_request +from .http import read_request +from .protocol import WebSocketCommonProtocol + + +__all__ = ["serve", "unix_serve", "WebSocketServerProtocol", "WebSocketServer"] + + +HeadersLikeOrCallable = Union[HeadersLike, Callable[[str, Headers], HeadersLike]] + +HTTPResponse = Tuple[http.HTTPStatus, HeadersLike, bytes] + + +class WebSocketServerProtocol(WebSocketCommonProtocol): + """ + WebSocket server connection. + + :class:`WebSocketServerProtocol` provides :meth:`recv` and :meth:`send` + coroutines for receiving and sending messages. + + It supports asynchronous iteration to receive messages:: + + async for message in websocket: + await process(message) + + The iterator exits normally when the connection is closed with close code + 1000 (OK) or 1001 (going away). It raises + a :exc:`~websockets.exceptions.ConnectionClosedError` when the connection + is closed with any other code. + + You may customize the opening handshake in a subclass by + overriding :meth:`process_request` or :meth:`select_subprotocol`. + + Args: + ws_server: WebSocket server that created this connection. + + See :func:`serve` for the documentation of ``ws_handler``, ``logger``, ``origins``, + ``extensions``, ``subprotocols``, and ``extra_headers``. + + See :class:`~websockets.legacy.protocol.WebSocketCommonProtocol` for the + documentation of ``ping_interval``, ``ping_timeout``, ``close_timeout``, + ``max_size``, ``max_queue``, ``read_limit``, and ``write_limit``. + + """ + + is_client = False + side = "server" + + def __init__( + self, + ws_handler: Union[ + Callable[[WebSocketServerProtocol], Awaitable[Any]], + Callable[[WebSocketServerProtocol, str], Awaitable[Any]], # deprecated + ], + ws_server: WebSocketServer, + *, + logger: Optional[LoggerLike] = None, + origins: Optional[Sequence[Optional[Origin]]] = None, + extensions: Optional[Sequence[ServerExtensionFactory]] = None, + subprotocols: Optional[Sequence[Subprotocol]] = None, + extra_headers: Optional[HeadersLikeOrCallable] = None, + process_request: Optional[ + Callable[[str, Headers], Awaitable[Optional[HTTPResponse]]] + ] = None, + select_subprotocol: Optional[ + Callable[[Sequence[Subprotocol], Sequence[Subprotocol]], Subprotocol] + ] = None, + **kwargs: Any, + ) -> None: + if logger is None: + logger = logging.getLogger("websockets.server") + super().__init__(logger=logger, **kwargs) + # For backwards compatibility with 6.0 or earlier. + if origins is not None and "" in origins: + warnings.warn("use None instead of '' in origins", DeprecationWarning) + origins = [None if origin == "" else origin for origin in origins] + # For backwards compatibility with 10.0 or earlier. Done here in + # addition to serve to trigger the deprecation warning on direct + # use of WebSocketServerProtocol. + self.ws_handler = remove_path_argument(ws_handler) + self.ws_server = ws_server + self.origins = origins + self.available_extensions = extensions + self.available_subprotocols = subprotocols + self.extra_headers = extra_headers + self._process_request = process_request + self._select_subprotocol = select_subprotocol + + def connection_made(self, transport: asyncio.BaseTransport) -> None: + """ + Register connection and initialize a task to handle it. + + """ + super().connection_made(transport) + # Register the connection with the server before creating the handler + # task. Registering at the beginning of the handler coroutine would + # create a race condition between the creation of the task, which + # schedules its execution, and the moment the handler starts running. + self.ws_server.register(self) + self.handler_task = self.loop.create_task(self.handler()) + + async def handler(self) -> None: + """ + Handle the lifecycle of a WebSocket connection. + + Since this method doesn't have a caller able to handle exceptions, it + attemps to log relevant ones and guarantees that the TCP connection is + closed before exiting. + + """ + try: + + try: + await self.handshake( + origins=self.origins, + available_extensions=self.available_extensions, + available_subprotocols=self.available_subprotocols, + extra_headers=self.extra_headers, + ) + # Remove this branch when dropping support for Python < 3.8 + # because CancelledError no longer inherits Exception. + except asyncio.CancelledError: # pragma: no cover + raise + except ConnectionError: + raise + except Exception as exc: + if isinstance(exc, AbortHandshake): + status, headers, body = exc.status, exc.headers, exc.body + elif isinstance(exc, InvalidOrigin): + if self.debug: + self.logger.debug("! invalid origin", exc_info=True) + status, headers, body = ( + http.HTTPStatus.FORBIDDEN, + Headers(), + f"Failed to open a WebSocket connection: {exc}.\n".encode(), + ) + elif isinstance(exc, InvalidUpgrade): + if self.debug: + self.logger.debug("! invalid upgrade", exc_info=True) + status, headers, body = ( + http.HTTPStatus.UPGRADE_REQUIRED, + Headers([("Upgrade", "websocket")]), + ( + f"Failed to open a WebSocket connection: {exc}.\n" + f"\n" + f"You cannot access a WebSocket server directly " + f"with a browser. You need a WebSocket client.\n" + ).encode(), + ) + elif isinstance(exc, InvalidHandshake): + if self.debug: + self.logger.debug("! invalid handshake", exc_info=True) + status, headers, body = ( + http.HTTPStatus.BAD_REQUEST, + Headers(), + f"Failed to open a WebSocket connection: {exc}.\n".encode(), + ) + else: + self.logger.error("opening handshake failed", exc_info=True) + status, headers, body = ( + http.HTTPStatus.INTERNAL_SERVER_ERROR, + Headers(), + ( + b"Failed to open a WebSocket connection.\n" + b"See server log for more information.\n" + ), + ) + + headers.setdefault("Date", email.utils.formatdate(usegmt=True)) + headers.setdefault("Server", USER_AGENT) + headers.setdefault("Content-Length", str(len(body))) + headers.setdefault("Content-Type", "text/plain") + headers.setdefault("Connection", "close") + + self.write_http_response(status, headers, body) + self.logger.info( + "connection failed (%d %s)", status.value, status.phrase + ) + await self.close_transport() + return + + try: + await self.ws_handler(self) + except Exception: + self.logger.error("connection handler failed", exc_info=True) + if not self.closed: + self.fail_connection(1011) + raise + + try: + await self.close() + except ConnectionError: + raise + except Exception: + self.logger.error("closing handshake failed", exc_info=True) + raise + + except Exception: + # Last-ditch attempt to avoid leaking connections on errors. + try: + self.transport.close() + except Exception: # pragma: no cover + pass + + finally: + # Unregister the connection with the server when the handler task + # terminates. Registration is tied to the lifecycle of the handler + # task because the server waits for tasks attached to registered + # connections before terminating. + self.ws_server.unregister(self) + self.logger.info("connection closed") + + async def read_http_request(self) -> Tuple[str, Headers]: + """ + Read request line and headers from the HTTP request. + + If the request contains a body, it may be read from ``self.reader`` + after this coroutine returns. + + Raises: + InvalidMessage: if the HTTP message is malformed or isn't an + HTTP/1.1 GET request. + + """ + try: + path, headers = await read_request(self.reader) + except asyncio.CancelledError: # pragma: no cover + raise + except Exception as exc: + raise InvalidMessage("did not receive a valid HTTP request") from exc + + if self.debug: + self.logger.debug("< GET %s HTTP/1.1", path) + for key, value in headers.raw_items(): + self.logger.debug("< %s: %s", key, value) + + self.path = path + self.request_headers = headers + + return path, headers + + def write_http_response( + self, status: http.HTTPStatus, headers: Headers, body: Optional[bytes] = None + ) -> None: + """ + Write status line and headers to the HTTP response. + + This coroutine is also able to write a response body. + + """ + self.response_headers = headers + + if self.debug: + self.logger.debug("> HTTP/1.1 %d %s", status.value, status.phrase) + for key, value in headers.raw_items(): + self.logger.debug("> %s: %s", key, value) + if body is not None: + self.logger.debug("> [body] (%d bytes)", len(body)) + + # Since the status line and headers only contain ASCII characters, + # we can keep this simple. + response = f"HTTP/1.1 {status.value} {status.phrase}\r\n" + response += str(headers) + + self.transport.write(response.encode()) + + if body is not None: + self.transport.write(body) + + async def process_request( + self, path: str, request_headers: Headers + ) -> Optional[HTTPResponse]: + """ + Intercept the HTTP request and return an HTTP response if appropriate. + + You may override this method in a :class:`WebSocketServerProtocol` + subclass, for example: + + * to return a HTTP 200 OK response on a given path; then a load + balancer can use this path for a health check; + * to authenticate the request and return a HTTP 401 Unauthorized or a + HTTP 403 Forbidden when authentication fails. + + You may also override this method with the ``process_request`` + argument of :func:`serve` and :class:`WebSocketServerProtocol`. This + is equivalent, except ``process_request`` won't have access to the + protocol instance, so it can't store information for later use. + + :meth:`process_request` is expected to complete quickly. If it may run + for a long time, then it should await :meth:`wait_closed` and exit if + :meth:`wait_closed` completes, or else it could prevent the server + from shutting down. + + Args: + path: request path, including optional query string. + request_headers: request headers. + + Returns: + Optional[Tuple[http.HTTPStatus, HeadersLike, bytes]]: :obj:`None` + to continue the WebSocket handshake normally. + + An HTTP response, represented by a 3-uple of the response status, + headers, and body, to abort the WebSocket handshake and return + that HTTP response instead. + + """ + if self._process_request is not None: + response = self._process_request(path, request_headers) + if isinstance(response, Awaitable): + return await response + else: + # For backwards compatibility with 7.0. + warnings.warn( + "declare process_request as a coroutine", DeprecationWarning + ) + return response + return None + + @staticmethod + def process_origin( + headers: Headers, origins: Optional[Sequence[Optional[Origin]]] = None + ) -> Optional[Origin]: + """ + Handle the Origin HTTP request header. + + Args: + headers: request headers. + origins: optional list of acceptable origins. + + Raises: + InvalidOrigin: if the origin isn't acceptable. + + """ + # "The user agent MUST NOT include more than one Origin header field" + # per https://www.rfc-editor.org/rfc/rfc6454.html#section-7.3. + try: + origin = cast(Optional[Origin], headers.get("Origin")) + except MultipleValuesError as exc: + raise InvalidHeader("Origin", "more than one Origin header found") from exc + if origins is not None: + if origin not in origins: + raise InvalidOrigin(origin) + return origin + + @staticmethod + def process_extensions( + headers: Headers, + available_extensions: Optional[Sequence[ServerExtensionFactory]], + ) -> Tuple[Optional[str], List[Extension]]: + """ + Handle the Sec-WebSocket-Extensions HTTP request header. + + Accept or reject each extension proposed in the client request. + Negotiate parameters for accepted extensions. + + Return the Sec-WebSocket-Extensions HTTP response header and the list + of accepted extensions. + + :rfc:`6455` leaves the rules up to the specification of each + :extension. + + To provide this level of flexibility, for each extension proposed by + the client, we check for a match with each extension available in the + server configuration. If no match is found, the extension is ignored. + + If several variants of the same extension are proposed by the client, + it may be accepted several times, which won't make sense in general. + Extensions must implement their own requirements. For this purpose, + the list of previously accepted extensions is provided. + + This process doesn't allow the server to reorder extensions. It can + only select a subset of the extensions proposed by the client. + + Other requirements, for example related to mandatory extensions or the + order of extensions, may be implemented by overriding this method. + + Args: + headers: request headers. + extensions: optional list of supported extensions. + + Raises: + InvalidHandshake: to abort the handshake with an HTTP 400 error. + + """ + response_header_value: Optional[str] = None + + extension_headers: List[ExtensionHeader] = [] + accepted_extensions: List[Extension] = [] + + header_values = headers.get_all("Sec-WebSocket-Extensions") + + if header_values and available_extensions: + + parsed_header_values: List[ExtensionHeader] = sum( + [parse_extension(header_value) for header_value in header_values], [] + ) + + for name, request_params in parsed_header_values: + + for ext_factory in available_extensions: + + # Skip non-matching extensions based on their name. + if ext_factory.name != name: + continue + + # Skip non-matching extensions based on their params. + try: + response_params, extension = ext_factory.process_request_params( + request_params, accepted_extensions + ) + except NegotiationError: + continue + + # Add matching extension to the final list. + extension_headers.append((name, response_params)) + accepted_extensions.append(extension) + + # Break out of the loop once we have a match. + break + + # If we didn't break from the loop, no extension in our list + # matched what the client sent. The extension is declined. + + # Serialize extension header. + if extension_headers: + response_header_value = build_extension(extension_headers) + + return response_header_value, accepted_extensions + + # Not @staticmethod because it calls self.select_subprotocol() + def process_subprotocol( + self, headers: Headers, available_subprotocols: Optional[Sequence[Subprotocol]] + ) -> Optional[Subprotocol]: + """ + Handle the Sec-WebSocket-Protocol HTTP request header. + + Return Sec-WebSocket-Protocol HTTP response header, which is the same + as the selected subprotocol. + + Args: + headers: request headers. + available_subprotocols: optional list of supported subprotocols. + + Raises: + InvalidHandshake: to abort the handshake with an HTTP 400 error. + + """ + subprotocol: Optional[Subprotocol] = None + + header_values = headers.get_all("Sec-WebSocket-Protocol") + + if header_values and available_subprotocols: + + parsed_header_values: List[Subprotocol] = sum( + [parse_subprotocol(header_value) for header_value in header_values], [] + ) + + subprotocol = self.select_subprotocol( + parsed_header_values, available_subprotocols + ) + + return subprotocol + + def select_subprotocol( + self, + client_subprotocols: Sequence[Subprotocol], + server_subprotocols: Sequence[Subprotocol], + ) -> Optional[Subprotocol]: + """ + Pick a subprotocol among those offered by the client. + + If several subprotocols are supported by the client and the server, + the default implementation selects the preferred subprotocol by + giving equal value to the priorities of the client and the server. + If no subprotocol is supported by the client and the server, it + proceeds without a subprotocol. + + This is unlikely to be the most useful implementation in practice. + Many servers providing a subprotocol will require that the client + uses that subprotocol. Such rules can be implemented in a subclass. + + You may also override this method with the ``select_subprotocol`` + argument of :func:`serve` and :class:`WebSocketServerProtocol`. + + Args: + client_subprotocols: list of subprotocols offered by the client. + server_subprotocols: list of subprotocols available on the server. + + Returns: + Optional[Subprotocol]: Selected subprotocol. + + :obj:`None` to continue without a subprotocol. + + + """ + if self._select_subprotocol is not None: + return self._select_subprotocol(client_subprotocols, server_subprotocols) + + subprotocols = set(client_subprotocols) & set(server_subprotocols) + if not subprotocols: + return None + priority = lambda p: ( + client_subprotocols.index(p) + server_subprotocols.index(p) + ) + return sorted(subprotocols, key=priority)[0] + + async def handshake( + self, + origins: Optional[Sequence[Optional[Origin]]] = None, + available_extensions: Optional[Sequence[ServerExtensionFactory]] = None, + available_subprotocols: Optional[Sequence[Subprotocol]] = None, + extra_headers: Optional[HeadersLikeOrCallable] = None, + ) -> str: + """ + Perform the server side of the opening handshake. + + Args: + origins: list of acceptable values of the Origin HTTP header; + include :obj:`None` if the lack of an origin is acceptable. + extensions: list of supported extensions, in order in which they + should be tried. + subprotocols: list of supported subprotocols, in order of + decreasing preference. + extra_headers: arbitrary HTTP headers to add to the response when + the handshake succeeds. + + Returns: + str: path of the URI of the request. + + Raises: + InvalidHandshake: if the handshake fails. + + """ + path, request_headers = await self.read_http_request() + + # Hook for customizing request handling, for example checking + # authentication or treating some paths as plain HTTP endpoints. + early_response_awaitable = self.process_request(path, request_headers) + if isinstance(early_response_awaitable, Awaitable): + early_response = await early_response_awaitable + else: + # For backwards compatibility with 7.0. + warnings.warn("declare process_request as a coroutine", DeprecationWarning) + early_response = early_response_awaitable + + # The connection may drop while process_request is running. + if self.state is State.CLOSED: + raise self.connection_closed_exc() # pragma: no cover + + # Change the response to a 503 error if the server is shutting down. + if not self.ws_server.is_serving(): + early_response = ( + http.HTTPStatus.SERVICE_UNAVAILABLE, + [], + b"Server is shutting down.\n", + ) + + if early_response is not None: + raise AbortHandshake(*early_response) + + key = check_request(request_headers) + + self.origin = self.process_origin(request_headers, origins) + + extensions_header, self.extensions = self.process_extensions( + request_headers, available_extensions + ) + + protocol_header = self.subprotocol = self.process_subprotocol( + request_headers, available_subprotocols + ) + + response_headers = Headers() + + build_response(response_headers, key) + + if extensions_header is not None: + response_headers["Sec-WebSocket-Extensions"] = extensions_header + + if protocol_header is not None: + response_headers["Sec-WebSocket-Protocol"] = protocol_header + + if callable(extra_headers): + extra_headers = extra_headers(path, self.request_headers) + if extra_headers is not None: + response_headers.update(extra_headers) + + response_headers.setdefault("Date", email.utils.formatdate(usegmt=True)) + response_headers.setdefault("Server", USER_AGENT) + + self.write_http_response(http.HTTPStatus.SWITCHING_PROTOCOLS, response_headers) + + self.logger.info("connection open") + + self.connection_open() + + return path + + +class WebSocketServer: + """ + WebSocket server returned by :func:`serve`. + + This class provides the same interface as :class:`~asyncio.Server`, + notably the :meth:`~asyncio.Server.close` + and :meth:`~asyncio.Server.wait_closed` methods. + + It keeps track of WebSocket connections in order to close them properly + when shutting down. + + Args: + logger: logger for this server; + defaults to ``logging.getLogger("websockets.server")``; + see the :doc:`logging guide <../topics/logging>` for details. + + """ + + def __init__(self, logger: Optional[LoggerLike] = None): + if logger is None: + logger = logging.getLogger("websockets.server") + self.logger = logger + + # Keep track of active connections. + self.websockets: Set[WebSocketServerProtocol] = set() + + # Task responsible for closing the server and terminating connections. + self.close_task: Optional[asyncio.Task[None]] = None + + # Completed when the server is closed and connections are terminated. + self.closed_waiter: asyncio.Future[None] + + def wrap(self, server: asyncio.base_events.Server) -> None: + """ + Attach to a given :class:`~asyncio.Server`. + + Since :meth:`~asyncio.loop.create_server` doesn't support injecting a + custom ``Server`` class, the easiest solution that doesn't rely on + private :mod:`asyncio` APIs is to: + + - instantiate a :class:`WebSocketServer` + - give the protocol factory a reference to that instance + - call :meth:`~asyncio.loop.create_server` with the factory + - attach the resulting :class:`~asyncio.Server` with this method + + """ + self.server = server + for sock in server.sockets: + if sock.family == socket.AF_INET: + name = "%s:%d" % sock.getsockname() + elif sock.family == socket.AF_INET6: + name = "[%s]:%d" % sock.getsockname()[:2] + elif sock.family == socket.AF_UNIX: + name = sock.getsockname() + # In the unlikely event that someone runs websockets over a + # protocol other than IP or Unix sockets, avoid crashing. + else: # pragma: no cover + name = str(sock.getsockname()) + self.logger.info("server listening on %s", name) + + # Initialized here because we need a reference to the event loop. + # This should be moved back to __init__ in Python 3.10. + self.closed_waiter = server.get_loop().create_future() + + def register(self, protocol: WebSocketServerProtocol) -> None: + """ + Register a connection with this server. + + """ + self.websockets.add(protocol) + + def unregister(self, protocol: WebSocketServerProtocol) -> None: + """ + Unregister a connection with this server. + + """ + self.websockets.remove(protocol) + + def close(self) -> None: + """ + Close the server. + + This method: + + * closes the underlying :class:`~asyncio.Server`; + * rejects new WebSocket connections with an HTTP 503 (service + unavailable) error; this happens when the server accepted the TCP + connection but didn't complete the WebSocket opening handshake prior + to closing; + * closes open WebSocket connections with close code 1001 (going away). + + :meth:`close` is idempotent. + + """ + if self.close_task is None: + self.close_task = self.get_loop().create_task(self._close()) + + async def _close(self) -> None: + """ + Implementation of :meth:`close`. + + This calls :meth:`~asyncio.Server.close` on the underlying + :class:`~asyncio.Server` object to stop accepting new connections and + then closes open connections with close code 1001. + + """ + self.logger.info("server closing") + + # Stop accepting new connections. + self.server.close() + + # Wait until self.server.close() completes. + await self.server.wait_closed() + + # Wait until all accepted connections reach connection_made() and call + # register(). See https://bugs.python.org/issue34852 for details. + await asyncio.sleep(0, **loop_if_py_lt_38(self.get_loop())) + + # Close OPEN connections with status code 1001. Since the server was + # closed, handshake() closes OPENING connections with a HTTP 503 + # error. Wait until all connections are closed. + + close_tasks = [ + asyncio.create_task(websocket.close(1001)) + for websocket in self.websockets + if websocket.state is not State.CONNECTING + ] + # asyncio.wait doesn't accept an empty first argument. + if close_tasks: + await asyncio.wait( + close_tasks, + **loop_if_py_lt_38(self.get_loop()), + ) + + # Wait until all connection handlers are complete. + + # asyncio.wait doesn't accept an empty first argument. + if self.websockets: + await asyncio.wait( + [websocket.handler_task for websocket in self.websockets], + **loop_if_py_lt_38(self.get_loop()), + ) + + # Tell wait_closed() to return. + self.closed_waiter.set_result(None) + + self.logger.info("server closed") + + async def wait_closed(self) -> None: + """ + Wait until the server is closed. + + When :meth:`wait_closed` returns, all TCP connections are closed and + all connection handlers have returned. + + To ensure a fast shutdown, a connection handler should always be + awaiting at least one of: + + * :meth:`~WebSocketServerProtocol.recv`: when the connection is closed, + it raises :exc:`~websockets.exceptions.ConnectionClosedOK`; + * :meth:`~WebSocketServerProtocol.wait_closed`: when the connection is + closed, it returns. + + Then the connection handler is immediately notified of the shutdown; + it can clean up and exit. + + """ + await asyncio.shield(self.closed_waiter) + + def get_loop(self) -> asyncio.AbstractEventLoop: + """ + See :meth:`asyncio.Server.get_loop`. + + """ + return self.server.get_loop() + + def is_serving(self) -> bool: + """ + See :meth:`asyncio.Server.is_serving`. + + """ + return self.server.is_serving() + + async def start_serving(self) -> None: + """ + See :meth:`asyncio.Server.start_serving`. + + """ + await self.server.start_serving() # pragma: no cover + + async def serve_forever(self) -> None: + """ + See :meth:`asyncio.Server.serve_forever`. + + """ + await self.server.serve_forever() # pragma: no cover + + @property + def sockets(self) -> Iterable[socket.socket]: + """ + See :attr:`asyncio.Server.sockets`. + + """ + return self.server.sockets + + async def __aenter__(self) -> WebSocketServer: + return self # pragma: no cover + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: + self.close() # pragma: no cover + await self.wait_closed() # pragma: no cover + + +class Serve: + """ + Start a WebSocket server listening on ``host`` and ``port``. + + Whenever a client connects, the server creates a + :class:`WebSocketServerProtocol`, performs the opening handshake, and + delegates to the connection handler, ``ws_handler``. + + The handler receives the :class:`WebSocketServerProtocol` and uses it to + send and receive messages. + + Once the handler completes, either normally or with an exception, the + server performs the closing handshake and closes the connection. + + Awaiting :func:`serve` yields a :class:`WebSocketServer`. This object + provides :meth:`~WebSocketServer.close` and + :meth:`~WebSocketServer.wait_closed` methods for shutting down the server. + + :func:`serve` can be used as an asynchronous context manager:: + + stop = asyncio.Future() # set this future to exit the server + + async with serve(...): + await stop + + The server is shut down automatically when exiting the context. + + Args: + ws_handler: connection handler. It receives the WebSocket connection, + which is a :class:`WebSocketServerProtocol`, in argument. + host: network interfaces the server is bound to; + see :meth:`~asyncio.loop.create_server` for details. + port: TCP port the server listens on; + see :meth:`~asyncio.loop.create_server` for details. + create_protocol: factory for the :class:`asyncio.Protocol` managing + the connection; defaults to :class:`WebSocketServerProtocol`; may + be set to a wrapper or a subclass to customize connection handling. + logger: logger for this server; + defaults to ``logging.getLogger("websockets.server")``; + see the :doc:`logging guide <../topics/logging>` for details. + compression: shortcut that enables the "permessage-deflate" extension + by default; may be set to :obj:`None` to disable compression; + see the :doc:`compression guide <../topics/compression>` for details. + origins: acceptable values of the ``Origin`` header; include + :obj:`None` in the list if the lack of an origin is acceptable. + This is useful for defending against Cross-Site WebSocket + Hijacking attacks. + extensions: list of supported extensions, in order in which they + should be tried. + subprotocols: list of supported subprotocols, in order of decreasing + preference. + extra_headers (Union[HeadersLike, Callable[[str, Headers], HeadersLike]]): + arbitrary HTTP headers to add to the request; this can be + a :data:`~websockets.datastructures.HeadersLike` or a callable + taking the request path and headers in arguments and returning + a :data:`~websockets.datastructures.HeadersLike`. + process_request (Optional[Callable[[str, Headers], \ + Awaitable[Optional[Tuple[http.HTTPStatus, HeadersLike, bytes]]]]]): + intercept HTTP request before the opening handshake; + see :meth:`~WebSocketServerProtocol.process_request` for details. + select_subprotocol: select a subprotocol supported by the client; + see :meth:`~WebSocketServerProtocol.select_subprotocol` for details. + + See :class:`~websockets.legacy.protocol.WebSocketCommonProtocol` for the + documentation of ``ping_interval``, ``ping_timeout``, ``close_timeout``, + ``max_size``, ``max_queue``, ``read_limit``, and ``write_limit``. + + Any other keyword arguments are passed the event loop's + :meth:`~asyncio.loop.create_server` method. + + For example: + + * You can set ``ssl`` to a :class:`~ssl.SSLContext` to enable TLS. + + * You can set ``sock`` to a :obj:`~socket.socket` that you created + outside of websockets. + + Returns: + WebSocketServer: WebSocket server. + + """ + + def __init__( + self, + ws_handler: Union[ + Callable[[WebSocketServerProtocol], Awaitable[Any]], + Callable[[WebSocketServerProtocol, str], Awaitable[Any]], # deprecated + ], + host: Optional[Union[str, Sequence[str]]] = None, + port: Optional[int] = None, + *, + create_protocol: Optional[Callable[[Any], WebSocketServerProtocol]] = None, + logger: Optional[LoggerLike] = None, + compression: Optional[str] = "deflate", + origins: Optional[Sequence[Optional[Origin]]] = None, + extensions: Optional[Sequence[ServerExtensionFactory]] = None, + subprotocols: Optional[Sequence[Subprotocol]] = None, + extra_headers: Optional[HeadersLikeOrCallable] = None, + process_request: Optional[ + Callable[[str, Headers], Awaitable[Optional[HTTPResponse]]] + ] = None, + select_subprotocol: Optional[ + Callable[[Sequence[Subprotocol], Sequence[Subprotocol]], Subprotocol] + ] = None, + ping_interval: Optional[float] = 20, + ping_timeout: Optional[float] = 20, + close_timeout: Optional[float] = None, + max_size: Optional[int] = 2**20, + max_queue: Optional[int] = 2**5, + read_limit: int = 2**16, + write_limit: int = 2**16, + **kwargs: Any, + ) -> None: + # Backwards compatibility: close_timeout used to be called timeout. + timeout: Optional[float] = kwargs.pop("timeout", None) + if timeout is None: + timeout = 10 + else: + warnings.warn("rename timeout to close_timeout", DeprecationWarning) + # If both are specified, timeout is ignored. + if close_timeout is None: + close_timeout = timeout + + # Backwards compatibility: create_protocol used to be called klass. + klass: Optional[Type[WebSocketServerProtocol]] = kwargs.pop("klass", None) + if klass is None: + klass = WebSocketServerProtocol + else: + warnings.warn("rename klass to create_protocol", DeprecationWarning) + # If both are specified, klass is ignored. + if create_protocol is None: + create_protocol = klass + + # Backwards compatibility: recv() used to return None on closed connections + legacy_recv: bool = kwargs.pop("legacy_recv", False) + + # Backwards compatibility: the loop parameter used to be supported. + _loop: Optional[asyncio.AbstractEventLoop] = kwargs.pop("loop", None) + if _loop is None: + loop = asyncio.get_event_loop() + else: + loop = _loop + warnings.warn("remove loop argument", DeprecationWarning) + + ws_server = WebSocketServer(logger=logger) + + secure = kwargs.get("ssl") is not None + + if compression == "deflate": + extensions = enable_server_permessage_deflate(extensions) + elif compression is not None: + raise ValueError(f"unsupported compression: {compression}") + + if subprotocols is not None: + validate_subprotocols(subprotocols) + + factory = functools.partial( + create_protocol, + # For backwards compatibility with 10.0 or earlier. Done here in + # addition to WebSocketServerProtocol to trigger the deprecation + # warning once per serve() call rather than once per connection. + remove_path_argument(ws_handler), + ws_server, + host=host, + port=port, + secure=secure, + ping_interval=ping_interval, + ping_timeout=ping_timeout, + close_timeout=close_timeout, + max_size=max_size, + max_queue=max_queue, + read_limit=read_limit, + write_limit=write_limit, + loop=_loop, + legacy_recv=legacy_recv, + origins=origins, + extensions=extensions, + subprotocols=subprotocols, + extra_headers=extra_headers, + process_request=process_request, + select_subprotocol=select_subprotocol, + logger=logger, + ) + + if kwargs.pop("unix", False): + path: Optional[str] = kwargs.pop("path", None) + # unix_serve(path) must not specify host and port parameters. + assert host is None and port is None + create_server = functools.partial( + loop.create_unix_server, factory, path, **kwargs + ) + else: + create_server = functools.partial( + loop.create_server, factory, host, port, **kwargs + ) + + # This is a coroutine function. + self._create_server = create_server + self.ws_server = ws_server + + # async with serve(...) + + async def __aenter__(self) -> WebSocketServer: + return await self + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: + self.ws_server.close() + await self.ws_server.wait_closed() + + # await serve(...) + + def __await__(self) -> Generator[Any, None, WebSocketServer]: + # Create a suitable iterator by calling __await__ on a coroutine. + return self.__await_impl__().__await__() + + async def __await_impl__(self) -> WebSocketServer: + server = await self._create_server() + self.ws_server.wrap(server) + return self.ws_server + + # yield from serve(...) - remove when dropping Python < 3.10 + + __iter__ = __await__ + + +serve = Serve + + +def unix_serve( + ws_handler: Union[ + Callable[[WebSocketServerProtocol], Awaitable[Any]], + Callable[[WebSocketServerProtocol, str], Awaitable[Any]], # deprecated + ], + path: Optional[str] = None, + **kwargs: Any, +) -> Serve: + """ + Similar to :func:`serve`, but for listening on Unix sockets. + + This function builds upon the event + loop's :meth:`~asyncio.loop.create_unix_server` method. + + It is only available on Unix. + + It's useful for deploying a server behind a reverse proxy such as nginx. + + Args: + path: file system path to the Unix socket. + + """ + return serve(ws_handler, path=path, unix=True, **kwargs) + + +def remove_path_argument( + ws_handler: Union[ + Callable[[WebSocketServerProtocol], Awaitable[Any]], + Callable[[WebSocketServerProtocol, str], Awaitable[Any]], + ] +) -> Callable[[WebSocketServerProtocol], Awaitable[Any]]: + try: + inspect.signature(ws_handler).bind(None) + except TypeError: + try: + inspect.signature(ws_handler).bind(None, "") + except TypeError: # pragma: no cover + # ws_handler accepts neither one nor two arguments; leave it alone. + pass + else: + # ws_handler accepts two arguments; activate backwards compatibility. + + # Enable deprecation warning and announce deprecation in 11.0. + # warnings.warn("remove second argument of ws_handler", DeprecationWarning) + + async def _ws_handler(websocket: WebSocketServerProtocol) -> Any: + return await cast( + Callable[[WebSocketServerProtocol, str], Awaitable[Any]], + ws_handler, + )(websocket, websocket.path) + + return _ws_handler + + return cast( + Callable[[WebSocketServerProtocol], Awaitable[Any]], + ws_handler, + ) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/py.typed b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/server.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/server.py new file mode 100644 index 00000000..5dad50b6 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/server.py @@ -0,0 +1,521 @@ +from __future__ import annotations + +import base64 +import binascii +import email.utils +import http +from typing import Generator, List, Optional, Sequence, Tuple, cast + +from .connection import CONNECTING, OPEN, SERVER, Connection, State +from .datastructures import Headers, MultipleValuesError +from .exceptions import ( + InvalidHandshake, + InvalidHeader, + InvalidHeaderValue, + InvalidOrigin, + InvalidStatus, + InvalidUpgrade, + NegotiationError, +) +from .extensions import Extension, ServerExtensionFactory +from .headers import ( + build_extension, + parse_connection, + parse_extension, + parse_subprotocol, + parse_upgrade, +) +from .http import USER_AGENT +from .http11 import Request, Response +from .typing import ( + ConnectionOption, + ExtensionHeader, + LoggerLike, + Origin, + Subprotocol, + UpgradeProtocol, +) +from .utils import accept_key + + +# See #940 for why lazy_import isn't used here for backwards compatibility. +from .legacy.server import * # isort:skip # noqa + + +__all__ = ["ServerConnection"] + + +class ServerConnection(Connection): + """ + Sans-I/O implementation of a WebSocket server connection. + + Args: + origins: acceptable values of the ``Origin`` header; include + :obj:`None` in the list if the lack of an origin is acceptable. + This is useful for defending against Cross-Site WebSocket + Hijacking attacks. + extensions: list of supported extensions, in order in which they + should be tried. + subprotocols: list of supported subprotocols, in order of decreasing + preference. + state: initial state of the WebSocket connection. + max_size: maximum size of incoming messages in bytes; + :obj:`None` to disable the limit. + logger: logger for this connection; + defaults to ``logging.getLogger("websockets.client")``; + see the :doc:`logging guide <../topics/logging>` for details. + + """ + + def __init__( + self, + origins: Optional[Sequence[Optional[Origin]]] = None, + extensions: Optional[Sequence[ServerExtensionFactory]] = None, + subprotocols: Optional[Sequence[Subprotocol]] = None, + state: State = CONNECTING, + max_size: Optional[int] = 2**20, + logger: Optional[LoggerLike] = None, + ): + super().__init__( + side=SERVER, + state=state, + max_size=max_size, + logger=logger, + ) + self.origins = origins + self.available_extensions = extensions + self.available_subprotocols = subprotocols + + def accept(self, request: Request) -> Response: + """ + Create a handshake response to accept the connection. + + If the connection cannot be established, the handshake response + actually rejects the handshake. + + You must send the handshake response with :meth:`send_response`. + + You can modify it before sending it, for example to add HTTP headers. + + Args: + request: WebSocket handshake request event received from the client. + + Returns: + Response: WebSocket handshake response event to send to the client. + + """ + try: + ( + accept_header, + extensions_header, + protocol_header, + ) = self.process_request(request) + except InvalidOrigin as exc: + request._exception = exc + self.handshake_exc = exc + if self.debug: + self.logger.debug("! invalid origin", exc_info=True) + return self.reject( + http.HTTPStatus.FORBIDDEN, + f"Failed to open a WebSocket connection: {exc}.\n", + ) + except InvalidUpgrade as exc: + request._exception = exc + self.handshake_exc = exc + if self.debug: + self.logger.debug("! invalid upgrade", exc_info=True) + response = self.reject( + http.HTTPStatus.UPGRADE_REQUIRED, + ( + f"Failed to open a WebSocket connection: {exc}.\n" + f"\n" + f"You cannot access a WebSocket server directly " + f"with a browser. You need a WebSocket client.\n" + ), + ) + response.headers["Upgrade"] = "websocket" + return response + except InvalidHandshake as exc: + request._exception = exc + self.handshake_exc = exc + if self.debug: + self.logger.debug("! invalid handshake", exc_info=True) + return self.reject( + http.HTTPStatus.BAD_REQUEST, + f"Failed to open a WebSocket connection: {exc}.\n", + ) + except Exception as exc: + request._exception = exc + self.handshake_exc = exc + self.logger.error("opening handshake failed", exc_info=True) + return self.reject( + http.HTTPStatus.INTERNAL_SERVER_ERROR, + ( + "Failed to open a WebSocket connection.\n" + "See server log for more information.\n" + ), + ) + + headers = Headers() + + headers["Date"] = email.utils.formatdate(usegmt=True) + + headers["Upgrade"] = "websocket" + headers["Connection"] = "Upgrade" + headers["Sec-WebSocket-Accept"] = accept_header + + if extensions_header is not None: + headers["Sec-WebSocket-Extensions"] = extensions_header + + if protocol_header is not None: + headers["Sec-WebSocket-Protocol"] = protocol_header + + headers["Server"] = USER_AGENT + + self.logger.info("connection open") + return Response(101, "Switching Protocols", headers) + + def process_request( + self, request: Request + ) -> Tuple[str, Optional[str], Optional[str]]: + """ + Check a handshake request and negotiate extensions and subprotocol. + + This function doesn't verify that the request is an HTTP/1.1 or higher + GET request and doesn't check the ``Host`` header. These controls are + usually performed earlier in the HTTP request handling code. They're + the responsibility of the caller. + + Args: + request: WebSocket handshake request received from the client. + + Returns: + Tuple[str, Optional[str], Optional[str]]: + ``Sec-WebSocket-Accept``, ``Sec-WebSocket-Extensions``, and + ``Sec-WebSocket-Protocol`` headers for the handshake response. + + Raises: + InvalidHandshake: if the handshake request is invalid; + then the server must return 400 Bad Request error. + + """ + headers = request.headers + + connection: List[ConnectionOption] = sum( + [parse_connection(value) for value in headers.get_all("Connection")], [] + ) + + if not any(value.lower() == "upgrade" for value in connection): + raise InvalidUpgrade( + "Connection", ", ".join(connection) if connection else None + ) + + upgrade: List[UpgradeProtocol] = sum( + [parse_upgrade(value) for value in headers.get_all("Upgrade")], [] + ) + + # For compatibility with non-strict implementations, ignore case when + # checking the Upgrade header. The RFC always uses "websocket", except + # in section 11.2. (IANA registration) where it uses "WebSocket". + if not (len(upgrade) == 1 and upgrade[0].lower() == "websocket"): + raise InvalidUpgrade("Upgrade", ", ".join(upgrade) if upgrade else None) + + try: + key = headers["Sec-WebSocket-Key"] + except KeyError as exc: + raise InvalidHeader("Sec-WebSocket-Key") from exc + except MultipleValuesError as exc: + raise InvalidHeader( + "Sec-WebSocket-Key", "more than one Sec-WebSocket-Key header found" + ) from exc + + try: + raw_key = base64.b64decode(key.encode(), validate=True) + except binascii.Error as exc: + raise InvalidHeaderValue("Sec-WebSocket-Key", key) from exc + if len(raw_key) != 16: + raise InvalidHeaderValue("Sec-WebSocket-Key", key) + + try: + version = headers["Sec-WebSocket-Version"] + except KeyError as exc: + raise InvalidHeader("Sec-WebSocket-Version") from exc + except MultipleValuesError as exc: + raise InvalidHeader( + "Sec-WebSocket-Version", + "more than one Sec-WebSocket-Version header found", + ) from exc + + if version != "13": + raise InvalidHeaderValue("Sec-WebSocket-Version", version) + + accept_header = accept_key(key) + + self.origin = self.process_origin(headers) + + extensions_header, self.extensions = self.process_extensions(headers) + + protocol_header = self.subprotocol = self.process_subprotocol(headers) + + return ( + accept_header, + extensions_header, + protocol_header, + ) + + def process_origin(self, headers: Headers) -> Optional[Origin]: + """ + Handle the Origin HTTP request header. + + Args: + headers: WebSocket handshake request headers. + + Returns: + Optional[Origin]: origin, if it is acceptable. + + Raises: + InvalidOrigin: if the origin isn't acceptable. + + """ + # "The user agent MUST NOT include more than one Origin header field" + # per https://www.rfc-editor.org/rfc/rfc6454.html#section-7.3. + try: + origin = cast(Optional[Origin], headers.get("Origin")) + except MultipleValuesError as exc: + raise InvalidHeader("Origin", "more than one Origin header found") from exc + if self.origins is not None: + if origin not in self.origins: + raise InvalidOrigin(origin) + return origin + + def process_extensions( + self, + headers: Headers, + ) -> Tuple[Optional[str], List[Extension]]: + """ + Handle the Sec-WebSocket-Extensions HTTP request header. + + Accept or reject each extension proposed in the client request. + Negotiate parameters for accepted extensions. + + :rfc:`6455` leaves the rules up to the specification of each + :extension. + + To provide this level of flexibility, for each extension proposed by + the client, we check for a match with each extension available in the + server configuration. If no match is found, the extension is ignored. + + If several variants of the same extension are proposed by the client, + it may be accepted several times, which won't make sense in general. + Extensions must implement their own requirements. For this purpose, + the list of previously accepted extensions is provided. + + This process doesn't allow the server to reorder extensions. It can + only select a subset of the extensions proposed by the client. + + Other requirements, for example related to mandatory extensions or the + order of extensions, may be implemented by overriding this method. + + Args: + headers: WebSocket handshake request headers. + + Returns: + Tuple[Optional[str], List[Extension]]: ``Sec-WebSocket-Extensions`` + HTTP response header and list of accepted extensions. + + Raises: + InvalidHandshake: to abort the handshake with an HTTP 400 error. + + """ + response_header_value: Optional[str] = None + + extension_headers: List[ExtensionHeader] = [] + accepted_extensions: List[Extension] = [] + + header_values = headers.get_all("Sec-WebSocket-Extensions") + + if header_values and self.available_extensions: + + parsed_header_values: List[ExtensionHeader] = sum( + [parse_extension(header_value) for header_value in header_values], [] + ) + + for name, request_params in parsed_header_values: + + for ext_factory in self.available_extensions: + + # Skip non-matching extensions based on their name. + if ext_factory.name != name: + continue + + # Skip non-matching extensions based on their params. + try: + response_params, extension = ext_factory.process_request_params( + request_params, accepted_extensions + ) + except NegotiationError: + continue + + # Add matching extension to the final list. + extension_headers.append((name, response_params)) + accepted_extensions.append(extension) + + # Break out of the loop once we have a match. + break + + # If we didn't break from the loop, no extension in our list + # matched what the client sent. The extension is declined. + + # Serialize extension header. + if extension_headers: + response_header_value = build_extension(extension_headers) + + return response_header_value, accepted_extensions + + def process_subprotocol(self, headers: Headers) -> Optional[Subprotocol]: + """ + Handle the Sec-WebSocket-Protocol HTTP request header. + + Args: + headers: WebSocket handshake request headers. + + Returns: + Optional[Subprotocol]: Subprotocol, if one was selected; this is + also the value of the ``Sec-WebSocket-Protocol`` response header. + + Raises: + InvalidHandshake: to abort the handshake with an HTTP 400 error. + + """ + subprotocol: Optional[Subprotocol] = None + + header_values = headers.get_all("Sec-WebSocket-Protocol") + + if header_values and self.available_subprotocols: + + parsed_header_values: List[Subprotocol] = sum( + [parse_subprotocol(header_value) for header_value in header_values], [] + ) + + subprotocol = self.select_subprotocol( + parsed_header_values, self.available_subprotocols + ) + + return subprotocol + + def select_subprotocol( + self, + client_subprotocols: Sequence[Subprotocol], + server_subprotocols: Sequence[Subprotocol], + ) -> Optional[Subprotocol]: + """ + Pick a subprotocol among those offered by the client. + + If several subprotocols are supported by the client and the server, + the default implementation selects the preferred subprotocols by + giving equal value to the priorities of the client and the server. + + If no common subprotocol is supported by the client and the server, it + proceeds without a subprotocol. + + This is unlikely to be the most useful implementation in practice, as + many servers providing a subprotocol will require that the client uses + that subprotocol. + + Args: + client_subprotocols: list of subprotocols offered by the client. + server_subprotocols: list of subprotocols available on the server. + + Returns: + Optional[Subprotocol]: Subprotocol, if a common subprotocol was + found. + + """ + subprotocols = set(client_subprotocols) & set(server_subprotocols) + if not subprotocols: + return None + priority = lambda p: ( + client_subprotocols.index(p) + server_subprotocols.index(p) + ) + return sorted(subprotocols, key=priority)[0] + + def reject( + self, + status: http.HTTPStatus, + text: str, + ) -> Response: + """ + Create a handshake response to reject the connection. + + A short plain text response is the best fallback when failing to + establish a WebSocket connection. + + You must send the handshake response with :meth:`send_response`. + + You can modify it before sending it, for example to alter HTTP headers. + + Args: + status: HTTP status code. + text: HTTP response body; will be encoded to UTF-8. + + Returns: + Response: WebSocket handshake response event to send to the client. + + """ + body = text.encode() + headers = Headers( + [ + ("Date", email.utils.formatdate(usegmt=True)), + ("Connection", "close"), + ("Content-Length", str(len(body))), + ("Content-Type", "text/plain; charset=utf-8"), + ("Server", USER_AGENT), + ] + ) + response = Response(status.value, status.phrase, headers, body) + # When reject() is called from accept(), handshake_exc is already set. + # If a user calls reject(), set handshake_exc to guarantee invariant: + # "handshake_exc is None if and only if opening handshake succeded." + if self.handshake_exc is None: + self.handshake_exc = InvalidStatus(response) + self.logger.info("connection failed (%d %s)", status.value, status.phrase) + return response + + def send_response(self, response: Response) -> None: + """ + Send a handshake response to the client. + + Args: + response: WebSocket handshake response event to send. + + """ + if self.debug: + code, phrase = response.status_code, response.reason_phrase + self.logger.debug("> HTTP/1.1 %d %s", code, phrase) + for key, value in response.headers.raw_items(): + self.logger.debug("> %s: %s", key, value) + if response.body is not None: + self.logger.debug("> [body] (%d bytes)", len(response.body)) + + self.writes.append(response.serialize()) + + if response.status_code == 101: + assert self.state is CONNECTING + self.state = OPEN + else: + self.send_eof() + self.parser = self.discard() + next(self.parser) # start coroutine + + def parse(self) -> Generator[None, None, None]: + if self.state is CONNECTING: + request = yield from Request.parse(self.reader.read_line) + + if self.debug: + self.logger.debug("< GET %s HTTP/1.1", request.path) + for key, value in request.headers.raw_items(): + self.logger.debug("< %s: %s", key, value) + + self.events.append(request) + + yield from super().parse() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/speedups.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/speedups.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..441b89e6f650af3ba66d2550e3c7eaff6804929c GIT binary patch literal 11264 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 None: + self.buffer = bytearray() + self.eof = False + + def read_line(self, m: int) -> Generator[None, None, bytes]: + """ + Read a LF-terminated line from the stream. + + This is a generator-based coroutine. + + The return value includes the LF character. + + Args: + m: maximum number bytes to read; this is a security limit. + + Raises: + EOFError: if the stream ends without a LF. + RuntimeError: if the stream ends in more than ``m`` bytes. + + """ + n = 0 # number of bytes to read + p = 0 # number of bytes without a newline + while True: + n = self.buffer.find(b"\n", p) + 1 + if n > 0: + break + p = len(self.buffer) + if p > m: + raise RuntimeError(f"read {p} bytes, expected no more than {m} bytes") + if self.eof: + raise EOFError(f"stream ends after {p} bytes, before end of line") + yield + if n > m: + raise RuntimeError(f"read {n} bytes, expected no more than {m} bytes") + r = self.buffer[:n] + del self.buffer[:n] + return r + + def read_exact(self, n: int) -> Generator[None, None, bytes]: + """ + Read a given number of bytes from the stream. + + This is a generator-based coroutine. + + Args: + n: how many bytes to read. + + Raises: + EOFError: if the stream ends in less than ``n`` bytes. + + """ + assert n >= 0 + while len(self.buffer) < n: + if self.eof: + p = len(self.buffer) + raise EOFError(f"stream ends after {p} bytes, expected {n} bytes") + yield + r = self.buffer[:n] + del self.buffer[:n] + return r + + def read_to_eof(self, m: int) -> Generator[None, None, bytes]: + """ + Read all bytes from the stream. + + This is a generator-based coroutine. + + Args: + m: maximum number bytes to read; this is a security limit. + + Raises: + RuntimeError: if the stream ends in more than ``m`` bytes. + + """ + while not self.eof: + p = len(self.buffer) + if p > m: + raise RuntimeError(f"read {p} bytes, expected no more than {m} bytes") + yield + r = self.buffer[:] + del self.buffer[:] + return r + + def at_eof(self) -> Generator[None, None, bool]: + """ + Tell whether the stream has ended and all data was read. + + This is a generator-based coroutine. + + """ + while True: + if self.buffer: + return False + if self.eof: + return True + # When all data was read but the stream hasn't ended, we can't + # tell if until either feed_data() or feed_eof() is called. + yield + + def feed_data(self, data: bytes) -> None: + """ + Write data to the stream. + + :meth:`feed_data` cannot be called after :meth:`feed_eof`. + + Args: + data: data to write. + + Raises: + EOFError: if the stream has ended. + + """ + if self.eof: + raise EOFError("stream ended") + self.buffer += data + + def feed_eof(self) -> None: + """ + End the stream. + + :meth:`feed_eof` cannot be called more than once. + + Raises: + EOFError: if the stream has ended. + + """ + if self.eof: + raise EOFError("stream ended") + self.eof = True + + def discard(self) -> None: + """ + Discard all buffered data, but don't end the stream. + + """ + del self.buffer[:] diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/typing.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/typing.py new file mode 100644 index 00000000..e672ba00 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/typing.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import logging +from typing import List, NewType, Optional, Tuple, Union + + +__all__ = [ + "Data", + "LoggerLike", + "Origin", + "Subprotocol", + "ExtensionName", + "ExtensionParameter", +] + + +# Public types used in the signature of public APIs + +Data = Union[str, bytes] +"""Types supported in a WebSocket message: +:class:`str` for a Text_ frame, :class:`bytes` for a Binary_. + +.. _Text: https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 +.. _Binary : https://www.rfc-editor.org/rfc/rfc6455.html#section-5.6 + +""" + + +LoggerLike = Union[logging.Logger, logging.LoggerAdapter] +"""Types accepted where a :class:`~logging.Logger` is expected.""" + + +Origin = NewType("Origin", str) +"""Value of a ``Origin`` header.""" + + +Subprotocol = NewType("Subprotocol", str) +"""Subprotocol in a ``Sec-WebSocket-Protocol`` header.""" + + +ExtensionName = NewType("ExtensionName", str) +"""Name of a WebSocket extension.""" + + +ExtensionParameter = Tuple[str, Optional[str]] +"""Parameter of a WebSocket extension.""" + + +# Private types + +ExtensionHeader = Tuple[ExtensionName, List[ExtensionParameter]] +"""Extension in a ``Sec-WebSocket-Extensions`` header.""" + + +ConnectionOption = NewType("ConnectionOption", str) +"""Connection option in a ``Connection`` header.""" + + +UpgradeProtocol = NewType("UpgradeProtocol", str) +"""Upgrade protocol in an ``Upgrade`` header.""" diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/uri.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/uri.py new file mode 100644 index 00000000..fff0c380 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/uri.py @@ -0,0 +1,108 @@ +from __future__ import annotations + +import dataclasses +import urllib.parse +from typing import Optional, Tuple + +from . import exceptions + + +__all__ = ["parse_uri", "WebSocketURI"] + + +@dataclasses.dataclass +class WebSocketURI: + """ + WebSocket URI. + + Attributes: + secure: :obj:`True` for a ``wss`` URI, :obj:`False` for a ``ws`` URI. + host: Normalized to lower case. + port: Always set even if it's the default. + path: May be empty. + query: May be empty if the URI doesn't include a query component. + username: Available when the URI contains `User Information`_. + password: Available when the URI contains `User Information`_. + + .. _User Information: https://www.rfc-editor.org/rfc/rfc3986.html#section-3.2.1 + + """ + + secure: bool + host: str + port: int + path: str + query: str + username: Optional[str] + password: Optional[str] + + @property + def resource_name(self) -> str: + if self.path: + resource_name = self.path + else: + resource_name = "/" + if self.query: + resource_name += "?" + self.query + return resource_name + + @property + def user_info(self) -> Optional[Tuple[str, str]]: + if self.username is None: + return None + assert self.password is not None + return (self.username, self.password) + + +# All characters from the gen-delims and sub-delims sets in RFC 3987. +DELIMS = ":/?#[]@!$&'()*+,;=" + + +def parse_uri(uri: str) -> WebSocketURI: + """ + Parse and validate a WebSocket URI. + + Args: + uri: WebSocket URI. + + Returns: + WebSocketURI: Parsed WebSocket URI. + + Raises: + InvalidURI: if ``uri`` isn't a valid WebSocket URI. + + """ + parsed = urllib.parse.urlparse(uri) + if parsed.scheme not in ["ws", "wss"]: + raise exceptions.InvalidURI(uri, "scheme isn't ws or wss") + if parsed.hostname is None: + raise exceptions.InvalidURI(uri, "hostname isn't provided") + if parsed.fragment != "": + raise exceptions.InvalidURI(uri, "fragment identifier is meaningless") + + secure = parsed.scheme == "wss" + host = parsed.hostname + port = parsed.port or (443 if secure else 80) + path = parsed.path + query = parsed.query + username = parsed.username + password = parsed.password + # urllib.parse.urlparse accepts URLs with a username but without a + # password. This doesn't make sense for HTTP Basic Auth credentials. + if username is not None and password is None: + raise exceptions.InvalidURI(uri, "username provided without password") + + try: + uri.encode("ascii") + except UnicodeEncodeError: + # Input contains non-ASCII characters. + # It must be an IRI. Convert it to a URI. + host = host.encode("idna").decode() + path = urllib.parse.quote(path, safe=DELIMS) + query = urllib.parse.quote(query, safe=DELIMS) + if username is not None: + assert password is not None + username = urllib.parse.quote(username, safe=DELIMS) + password = urllib.parse.quote(password, safe=DELIMS) + + return WebSocketURI(secure, host, port, path, query, username, password) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/utils.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/utils.py new file mode 100644 index 00000000..c4040490 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/utils.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import base64 +import hashlib +import secrets +import sys + + +__all__ = ["accept_key", "apply_mask"] + + +GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" + + +def generate_key() -> str: + """ + Generate a random key for the Sec-WebSocket-Key header. + + """ + key = secrets.token_bytes(16) + return base64.b64encode(key).decode() + + +def accept_key(key: str) -> str: + """ + Compute the value of the Sec-WebSocket-Accept header. + + Args: + key: value of the Sec-WebSocket-Key header. + + """ + sha1 = hashlib.sha1((key + GUID).encode()).digest() + return base64.b64encode(sha1).decode() + + +def apply_mask(data: bytes, mask: bytes) -> bytes: + """ + Apply masking to the data of a WebSocket message. + + Args: + data: data to mask. + mask: 4-bytes mask. + + """ + if len(mask) != 4: + raise ValueError("mask must contain 4 bytes") + + data_int = int.from_bytes(data, sys.byteorder) + mask_repeated = mask * (len(data) // 4) + mask[: len(data) % 4] + mask_int = int.from_bytes(mask_repeated, sys.byteorder) + return (data_int ^ mask_int).to_bytes(len(data), sys.byteorder) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/version.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/version.py new file mode 100644 index 00000000..c30bfd68 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/websockets/version.py @@ -0,0 +1,78 @@ +from __future__ import annotations + + +__all__ = ["tag", "version", "commit"] + + +# ========= =========== =================== +# release development +# ========= =========== =================== +# tag X.Y X.Y (upcoming) +# version X.Y X.Y.dev1+g5678cde +# commit X.Y 5678cde +# ========= =========== =================== + + +# When tagging a release, set `released = True`. +# After tagging a release, set `released = False` and increment `tag`. + +released = True + +tag = version = commit = "10.3" + + +if not released: # pragma: no cover + import pathlib + import re + import subprocess + + def get_version(tag: str) -> str: + # Since setup.py executes the contents of src/websockets/version.py, + # __file__ can point to either of these two files. + file_path = pathlib.Path(__file__) + root_dir = file_path.parents[0 if file_path.name == "setup.py" else 2] + + # Read version from git if available. This prevents reading stale + # information from src/websockets.egg-info after building a sdist. + try: + description = subprocess.run( + ["git", "describe", "--dirty", "--tags", "--long"], + capture_output=True, + cwd=root_dir, + timeout=1, + check=True, + text=True, + ).stdout.strip() + # subprocess.run raises FileNotFoundError if git isn't on $PATH. + except (FileNotFoundError, subprocess.CalledProcessError): + pass + else: + description_re = r"[0-9.]+-([0-9]+)-(g[0-9a-f]{7,}(?:-dirty)?)" + match = re.fullmatch(description_re, description) + assert match is not None + distance, remainder = match.groups() + remainder = remainder.replace("-", ".") # required by PEP 440 + return f"{tag}.dev{distance}+{remainder}" + + # Read version from package metadata if it is installed. + try: + import importlib.metadata # move up when dropping Python 3.7 + + return importlib.metadata.version("websockets") + except ImportError: + pass + + # Avoid crashing if the development version cannot be determined. + return f"{tag}.dev0+gunknown" + + version = get_version(tag) + + def get_commit(tag: str, version: str) -> str: + # Extract commit from version, falling back to tag if not available. + version_re = r"[0-9.]+\.dev[0-9]+\+g([0-9a-f]{7,}|unknown)(?:\.dirty)?" + match = re.fullmatch(version_re, version) + assert match is not None + (commit,) = match.groups() + return tag if commit == "unknown" else commit + + commit = get_commit(tag, version) diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Scripts/dotenv.exe b/Resources/WPy64-3720/python-3.7.2.amd64/Scripts/dotenv.exe new file mode 100644 index 0000000000000000000000000000000000000000..6479de8873795ed0f83baad5bd61497dde30812f GIT binary patch literal 106369 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 NncR-L^byzH{{ocj33LDe literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Scripts/uvicorn.exe b/Resources/WPy64-3720/python-3.7.2.amd64/Scripts/uvicorn.exe new file mode 100644 index 0000000000000000000000000000000000000000..44e93d24e0aed33b1bdb85fe6fae811db4636e33 GIT binary patch literal 106373 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Scripts/watchfiles.exe b/Resources/WPy64-3720/python-3.7.2.amd64/Scripts/watchfiles.exe new file mode 100644 index 0000000000000000000000000000000000000000..3f6a4a01a9dd40e4232afc3ffb89e1189639b6c3 GIT binary patch literal 106373 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 -import ssl -class RobotDaemonServer(Thread): - def __init__(self,name,inGlobalDict): - Thread.__init__(self) - self.name = name - # Update the global dict - ServerSettings.SettingsUpdate(inGlobalDict) - def run(self): - global gSettingsDict - lL = gSettingsDict.get("Logger",None) - try: - lServerDict = gSettingsDict["ServerDict"]["ListenDict"][self.name] - lAddressStr=lServerDict["AddressStr"] - lPortInt=lServerDict["PortInt"] - lCertFilePathStr = lServerDict["CertFilePEMPathStr"] - lKeyFilePathStr = lServerDict["KeyFilePathStr"] - if lCertFilePathStr == "": lCertFilePathStr = None - if lKeyFilePathStr == "": lKeyFilePathStr = None - # Server settings - # Choose port 8080, for port 80, which is normally used for a http server, you need root access - server_address = (lAddressStr, lPortInt) - #httpd = HTTPServer(server_address, testHTTPServer_RequestHandler) - #httpd.serve_forever() - httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler) - if lCertFilePathStr is not None: - if lKeyFilePathStr is not None: - httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr, keyfile=lKeyFilePathStr) - else: - httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr) - if lL: lL.info(f"Сервер инициализирован успешно (с поддержкой SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}, Путь к файлу сертификата (.pem): {lCertFilePathStr}") - else: - if lL: lL.info(f"Сервер инициализирован успешно (без поддержки SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}") - #print('Starting server, use to stop') - httpd.serve_forever() - except Exception as e: - if lL: lL.exception(f"Сервер:: Ошибка при инициализации - обратитесь в тех. поддержку pyOpenRPA") +from typing import Union +# объявление import +from fastapi import FastAPI, Form, Request, HTTPException, Depends, Header, Response +from fastapi.responses import PlainTextResponse, HTMLResponse, FileResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +from pydantic import BaseModel +import random +import uvicorn + + +# инициализация +app = FastAPI() + +# hello world, метод GET, возврат строки +#@app.get("/", response_class=PlainTextResponse) +#async def hello(): +# return "Hello World!" + + +def IdentifyAuthorize(inRequest:Request, inResponse:Response, + inCookiesStr: Union[str, None] = Header(default=None,alias="Cookie"), + inAuthorizationStr: Union[str, None] = Header(default="",alias="Authorization")): + lResult={"Domain": "", "User": ""} + ###################################### + #Way 1 - try to find AuthToken + lCookies = cookies.SimpleCookie(inCookiesStr) # inRequest.headers.get("Cookie", "") + global gSettingsDict + lHeaderAuthorization = inAuthorizationStr.split(" ") + if "AuthToken" in lCookies: + lCookieAuthToken = lCookies.get("AuthToken", "").value + if lCookieAuthToken: + #Find AuthToken in GlobalDict + if lCookieAuthToken in gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): + #Auth Token Has Been Founded + lResult["Domain"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] + lResult["User"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] + #Set auth token + inRequest.OpenRPA={} + inRequest.OpenRPA["AuthToken"] = lCookieAuthToken + inRequest.OpenRPA["Domain"] = lResult["Domain"] + inRequest.OpenRPA["User"] = lResult["User"] + #Exit earlier + return lResult + ###################################### + #Way 2 - try to logon + elif len(lHeaderAuthorization) == 2: + llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split( + ":") + lUser = llHeaderAuthorizationDecodedUserPasswordList[0] + lPassword = llHeaderAuthorizationDecodedUserPasswordList[1] + lDomain = "" + if "\\" in lUser: + lDomain = lUser.split("\\")[0] + lUser = lUser.split("\\")[1] + lLogonBool = __Orchestrator__.OSCredentialsVerify(inUserStr=lUser, inPasswordStr=lPassword, inDomainStr=lDomain) + #Check result + if lLogonBool: + lResult["Domain"] = lDomain + lResult["User"] = lUser + #Create token + lAuthToken=str(uuid.uuid1()) + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() + #Set-cookie + inResponse.set_cookie(key="AuthToken",value=lAuthToken) + inRequest.OpenRPA={} + inRequest.OpenRPA["AuthToken"] = lAuthToken + inRequest.OpenRPA["Domain"] = lResult["Domain"] + inRequest.OpenRPA["User"] = lResult["User"] + #inRequest.OpenRPASetCookie = {} + #New engine of server + #inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken + else: + raise HTTPException(status_code=401, detail="here is the details", headers={}) + ###################################### + else: + raise HTTPException(status_code=401, detail="here is the details", headers={'Content-type':'text/html', 'WWW-Authenticate':'Basic'}) + return True + + +def BackwardCompatibityWrapper(): # Old from v1.3.1 (updated to FastAPI) + lHTTPRequest = HTTPRequestOld() + lHTTPRequest.do_GET + lHTTPRequest.do_POST + +@app.get(path="/", response_class=PlainTextResponse) +def Hi(t:bool=Depends(IdentifyAuthorize)): + return "Hello world" + + +def FastAPI(): + global gSettingsDict + global app + lL = gSettingsDict.get("Logger",None) + + + #lThreadServer = Server.RobotDaemonServer(lItemKeyStr, gSettingsDict) + #lThreadServer.start() + gSettingsDict["ServerDict"]["ServerThread"] = app + app.add_api_route( + path="/", + endpoint=ServerSettings.pyOpenRPA_Index, + response_class=PlainTextResponse + ) + + #app.get("/", ServerSettings.pyOpenRPA_Index, response_class=PlainTextResponse) + + uvicorn.run('pyOpenRPA.Orchestrator.Server:app', host='0.0.0.0', port=1024) + + + if lL: lL.info(f"Сервер инициализирован успешно (с поддержкой SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}, Путь к файлу сертификата (.pem): {lCertFilePathStr}") + if lL: lL.info(f"Сервер инициализирован успешно (без поддержки SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}") + + + if lL: lL.info("Модуль сервера FASTAPI") #Logging \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py index 6550b079..e3223d89 100755 --- a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py +++ b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py @@ -41,6 +41,8 @@ import math import glob # search the files import urllib + + #Единый глобальный словарь (За основу взять из Settings.py) gSettingsDict = None @@ -2756,10 +2758,9 @@ def Orchestrator(inGSettings=None, inDumpRestoreBool = True, inRunAsAdministrato lListenDict = gSettingsDict.get("ServerDict",{}).get("ListenDict",{}) for lItemKeyStr in lListenDict: lItemDict = lListenDict[lItemKeyStr] - lThreadServer = Server.RobotDaemonServer(lItemKeyStr, gSettingsDict) - lThreadServer.start() - gSettingsDict["ServerDict"]["ServerThread"] = lThreadServer - lItemDict["ServerInstance"] = lThreadServer + Server.FastAPI() + + # Init the RobotScreenActive in another thread lRobotScreenActiveThread = threading.Thread(target= Monitor.CheckScreen) diff --git a/Studio/pyOpenRPA.Studio_x64.cmd b/Studio/pyOpenRPA.Studio_x64.cmd index cca2c1d4..39948a1d 100755 --- a/Studio/pyOpenRPA.Studio_x64.cmd +++ b/Studio/pyOpenRPA.Studio_x64.cmd @@ -1,4 +1,5 @@ -cd %~dp0\..\Sources +chcp 65001 +cd /d "%~dp0\..\Sources" copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Studio.exe .\..\Resources\WPy64-3720\python-3.7.2.amd64\OpenRPA_Studio.exe -m pyOpenRPA.Studio "..\Studio\SettingsStudioExample.py" pause >nul \ No newline at end of file
    2. W- zH?^D|{bY+PwLTi`^X`U%yz-`|pdmjO!A_6!ve->cN5co)6>=Khl|7==R%mF5ff;V7 z!7FcSM>JHWHT9 zRAEd74?GH(sRvw#2P!-Py>ve(X-voE)tl$Rci%NgJQGbT)9r(_x z1Qzbsi3`joV=^B@qXT)bDCUdVB~CH#2pWaFr7(Z% zs5T4k_lpZWPs&5xW0_@y&Q}Gam@j3QW#|I4v;mD`{<9qQwlU0k*bsPul%rxY-^Ex3 z@)ffp&GHhvG*ir90*zumTbQ3eqLK5sBJc_+%fw_phw%pHEuxsOV3*U~1o;rqDCYHq z`Fz71_Y21bUL)luP-ai#`*bM&G&2(U8|*S&F@Fs-iunKYuFHEbG{1m||WNGz$3#a#~!;Fvmj{ae)n_ygMfI zNyr*>=$I(x0d^^+n0E(_V%|rX?>wx{f~R5P0-H&Bu1hTBwV7zaynGb%E$p%$U09!h zMlmle%pWw&@gz`OU@IwS#$;Y1q?m7cGSV#D*`=#ueh!=9iur3EMoUq{9M5XS1$L71 zwwTO&YvjG7nD1hjJc@a$gZv(0{`P0uEO?SFF7PoaKf6DcS*HD{kQa(#zK302Ko^*$ z7ibjnU#=$dwuU*LB#aB}Bjuwpn8z+xRv!XSS-_c!vrOP9S=19@RyXX@Mwcsh%g!wq z4X5!}aE#w=f+N9t;duYJ1LeIuFjM8(C(J;Aj;w}r|Fim-bkyJvIZo#;sy_Q__I z@&OOKUF;+(mIR%0VJ6njA^Q!W6czDCfVeQ|AJzje&cJev#G<^?_8+l}s#oh#=9|4k9<3jZ=~@t@HYRZygMzM!EOvRWVZx?W6uMf^6o=e zM275r2ekG#Qu{kddA>s|0edk?Gkk82A>dAS+r(}@`(@B60UiG(gizLw01o-tjhMLn*Si)8oEP;p~Z>b(!upFe4{QuT_ukVD)1J+!G2e7c3JtFD+FdU ziahPI4|AVAmq&ldA$Lx72VRB1GwgDttpxc{(5M_z1$&qw`-#1J6x{^5f%&9-3zXRt z)Z4o5I{{4Lv{)hVEW13WnERc&@1y)=UehqINal-3*(N6Qg|rKhPl{sx9J?ea<|9F) zkUu2M_wCWhE0OsUQl4)U3;E-W3^2briup2j`2bxo_U{9YVqRRBKVq0yCi53bIX@=z z0rVP}@0uKGmY3P3k7C{oG>Z8u>?hzpS;PEhGG9*0J7O{)#8X-@9~8y>Rdy+?m}h`S zG4CME*Y4J4sY2$jlk%&3W0_^2j+SCk%->{}*U$xKdCiHIzp!)-+4mdfRmuEqQcj4; ze3`cSJCh>K@(#P)qnOh#3i%>o9{N}#$D1wV0`HQtQcUJ8Il^F;_EF4Nv&%271$i~l zDCQ}`e5qkxoy^ygawjOW$GPMYF#mI6B=Ys_GDk7r=pg?F>*A1|W|-F?^Npl@FedZg zPAcRJqnK}Em->qNKF}!SQ-pc&BW;$NWd1%Wi^gPL@RVZSD2n+9>~ge~nB|*q4fCqP z+-I2ABJ*ved>fS6%`!kE|9V2CS$43?SjD`VgZyLcMc}&-hIwr=|B#ezV=}L#<9u=y z^N-l&M#Vgj6Xy>L^ZmQDS#BZo-K6~Eo><5WY2;O+nD1qmt>}U{KlzO@O9^3~WtihV z<8gugq+Ae_`L8FG%|99+X_imerLSVX7c|PD?_!Y{vad7DZzc1Cq)d* zW0xX|`7f9#74we5eBFoIEWBwm@Hr`uw~S?$4>`jk&WlGeKguqzqYKRPqQm@eEL}r( z7sLEEGCxMji7}a%(acwki!{qu?9xgxzknG|Azv)a;|%jeGCx7e$}yQYIu{PeWWT%vkRxXKhJoM6nE45;Y2v+$OE7pob zB3SiQthl+IpsF%0qlBu;Qqb_s*KQeJUU_A6yPPT4e31&-~@|o5d?rC0h4?Zr6P1FqIB4&+ImGe zti3pF{9)BLIHIkGYCEplrbqA`t9S-gTTK0aQfth_FjJWtUQ_EiOWbUzDvARNM532p=mEKE8@-tFP8Q zdc0JVb$1R1{LyQ{X$h<%}GlAX{t@ey)%^JmFu5UZ6_j3`iU~>JZZBN3Bcz$j|~F6Cw7aT zN*W@b0<(G{QIEX~89aJp!`cCI+$>cpy@96}(%`UaFxE0m(&@Ng3(vctEqOLCy^jUY z)CT)*7{0-k@P^#f)*4rterqTx{Ps;?5G;`4nkYiJ+oIc$z(UHu*i0t9J@50My}=p7 z+;i8Ez+%!IAx$(!do=V^Q`z-Ii~Ao!_6V?%ZL=X%a0xpvLg#FArFDwSdZpmg`SZmM zs|*Dv;NYGLUJV5^eTk3Y@=SFoHvz^D9)z7lxhz~kxppM>+wIXgSQUz6UD;yt`C&y< z{auF!UZvoQO0x}{As<^ftFl}cko!%B23{xKKWQ-l+Px8QYDXstP;vJ|$X)bq_)lUlD{zQ3<46-}23R%IcQNYLp4wDTjQTqE zNyMmE!{1`mEE@F)x!nqG*`sl^?7m1Y*@-_Tmvmri2BYe3Dm*UHpkdA|1*h!R|hbt(zgv5Tk zA$@raZ7yF95By5Ohf}GNb&KpCh$-Jiq=_l7<^2_5Q(C+CjpH-C z@ZOaW-14xCx$Ycd=OXAFWkv*{+~MUOj&>cCA1dnVVb=mtiRa|jYo`pSQ}Xo&w+$%} z6YWvUl3g4z)fUtPVygM9=)yyvw7GJ} zh(J6g9cUzys)Z%}!Sv3#t6603sAqD=`A@;^dLt=_D@eLt<&Jge92_K)oVja6pg1M< zgCy<#8f!%FE)ZnG|LMMc7;2f`!3l6raNi&aUWfDsl9nOrDF0xxPWRz{ zaNa|hj(Zk)v%K6V`37cJ-Zkz?!(ia-j=RS3p6s>ab&tR6h(LMr+<9lV2!aucqmOn$ zQA~kim=-+U2`AM%aVai%{ScIogX_fK&*2J&Ng%P`-j9hR*cNTBfjBZym4feqU`TqI zfuWqe5MxrJ%g1r0qbt*AkHKZ8x7~56kER{~$5}9hNE?MKNbAfFe)~Q!2%e&mylKZX zefwHWKEMg1^T9a6UHx^Okz8C(FH ziQda`1-(m?!f*e|KtD%&MvSUafh5X5bq69a9|n2IUh%GD8y#7r0?DM=0vb4D)@rek zQ(a8pwYM>=ixKaEg5|0;2!G+n1pL|D`7uTPSS85Y)8TA~eLC6qB>SkqMbN5e8?qbr zhJ)I$Pw4GF3EgiYLK${cAd_4@;F`@>R(shmlXUgSS2}ce!9X;uu1DA7QbKpdJ{T?y z{t=@t#1)LXh{S&Tc61KTN1H2jM+e$d@a!a-3HPtg$rI` zB-A|*$1;yb)^t$y^gC{kJ|6Is%OK%mwcDNjHi1<9rquj{YOWj*ZK=ltv&fHhZ7Tng~v6W`xq}O-2rWwXWh;jLOm7F_FnExR(JM zP9>XhDXC;HXTiUKL{iE7Y8G5dVyxRa3$}zSbt;KpKY?~zO-Shi$$Fm49VMzJq{?*A zmW%Q5G?<1E;c{3<3|d8L*hx)zJckPYi#A=^Y3(*r)E|jX!L|MkQUq1J zh{-pJ{-9tKWcUuU@J7Xi`YS}U&-~%}(KmHCiz0i;?P}rHC64LH z$cJOwa@S5-xi}_6v9i?PPT1D$gsMxdoWOFb3A`g#E}_b)B-Uhp`_nUMdj@T=VT;K> zz@d{EwqH~9%-d)~yAvW?W~<%7S`yzZ z1x3nt>|9+sNAE3UG3JzhC%7PC)jpWNIr=3(fJ@QuCr+3>VJFe=Yg{2{n~>OVzre-F zYP2~~G@1JSOv!K81#GN*3rSJ0{V2`9vUwJpS&xxUT)R$f6W^ybc{I#eY_Jp)$q4rYc6Nb)7}l6oj+ zz~CYnO%(5iEBLzwDg1UbFbMukgNBQLtx`!M_ztH9aBHKm$QQ6m7Ll*&@Y1$kh)c)T zjgWzY)r`nGxPr(>RfzTEqI;|o8D;BI6qyB)ur+s%3Uy|zQF??rD1y($rTc|M<@L5ZCa9n;UuQbFX$v&$JoB4(@{M~D- z`a2;ww0Sh@1WH&)2`ay*fFddZU|SYbK(M5mmed3yL$3z=b{BM!qaJB5Td>&|w=;<_ zGfu|}1hYfPKC|4d>@8$hT-Ze=AgeQa=(y@jCo?m?!9nKakmToZDPwo;`*30g{2(zk z4OejRcoO^VYIN`-v^km4&ot4HlAo!?9MT<-9KX(BV^cOhibj}uD7ax3!~}61+Jx+C zMggI0M#@%-GTotk59M3Pj*FnYi_ZzUD!oD0E#*rbdGgr(YifITL!eSL>Aa-FYm{I6fXz4M0C7d^K)E^ zm&fgaCwszz;^m>Zf|u8m*l*89=iqAbgPz|-R4@EPJh}wiJh?+)XzrB{b7nveTw(;ZFi>N*n)l7+6%vxFHL?3paBtad~qI81# z2$xQRT8z;e^crzb;R@oGD{;-iAb5<{a!&>#vL8i$Ql0+CWUx2bx3f@%Cj+4xK&sbC z73pa;8HA!L!L{mE>dY4$fok*%tB1&{2Uw|1UM8J30S=GdYCEMFFR+~wJk}`|lHu%r zlOTyq9tz42QBW}C27M4QFX7!8ufC|mP5?bhj{B=YSabrmN~3nrK6vZ^eg>() zh(rzW1uh-8_vO4a3-%C^oz%Rvjvf5=QT!7;C8kb0?$iJxax6uDQB_3V78Y6Oj1KBJ zW)~-@YyONllI_O&NF_m?;c$Wv7;ql}>5GY6@A!ffcurxv243Kd+}%^%>zwTx59D5`v>U zM5CC&uG^|)iv^X?=;x@qy%>rf%uYz|nZ6%GcI##C$eKlNBfu@&sIdl1QRvy<6bAHJ zr8h@q?hFZ$85|TuT5UEZ*p$HRy*Icv)-jU3ev_F(Gr%{~_Xpnpu+$B7 z9@*@_3#va3)j2id%|N%b@aO@({{*N%=)(75_N*)I;uVguM*81QwHelw-&h$E7pmdZB0v zmWR=047A4;#=wtilylt`e1rky&a@)(J<(r8+V2Bg3*Q!mWXLWX0c;Jang~_4aR75q z!$yk6+6C!Fu#VBI5j`sm!li@tEz}#qM_>`bx)fKydN(`x?J~?(JLr&XSl1E7#!6xy zJ1nyFM>;*MMKUw#0jO5s@(fBwPX@*1H{z0%xalOuc|V3qu%i;!DkEvDaoPsTY7JR> zK--H2QAhAMBmt7tQgALlM^vy4<1MWtgr4OuUaS;-En3M>Uc8Hk)mA&aYpQpv;OsWS zu$7D9b}~Fx5x+<7VSq(P9Bp6^BfaYN!wRPRQVU@ZBh!}##(OcB^v6g-Ye&3K3qr%; zw2S=wavjiFCdDgh4dInZ;B-tyrZj56tbDVb4=Oh+EFdE1eZPTj(&1Q`tkqmZ2l>|y`EOK@e_ z+ER&m32R&Jj2obGQKazOvLEv;jpDAk zL}WRNJenZ(s2di!=7jcth*?h;Kv3`}TuO%POK}y9xK2vk0TTP|(dZl;uEcdrPuh<3 zC9)DI>tV>!8LsYpL3CUnSZS&Xq{>i;t``q+$3RW1g~dfYcueakXN|}~!3`~ijZTyz zsTz4${J???wbLt=Iz^}jD9xdk%8K2QfOS^v z=+263;1FiTX%V`nkmnS|Gh!NG;tSbH%I_M*TB2yq9&OPB1N|gcJ}~A+&M{B~@4o@P z_(4cBNm^ByTX~L)A%`v$Lykr@VHW>D-wUf+W60-Mx(&IazT1$(wFS9;QkG`Wh8#ws zoD3O^m`izcbf6PC%oGlh@c}4#o-u~3hYS(RkPpLvG-RU)UGFE)WW_UvA%6keusb&r zMIZLKN_tp5d77y5dH2utc&^R4H$0vba4F;YnT;5;_rj`@KD@X>KF>>HoKvB5@FiND z!6)NcWc8!0=gQD&EI{mQ5Xj17tpQ9tCUgTxHv)7LhptHy&i-Q#f428Qpcq?5PKk)_ z1KGX4bhqMAWn$#KUtS#E7`e=W;suwFIAs63dID>v z)=yKmUf=Gb(Vn542StvRG#lb%xl{*#aq11(<$=nXd!@%h_GqAb%tY<1BYG~&er{y` zyA{9bh|cuYJcmoEP--G~2FJma64B*xg^1oqV!z#qCI6>rbC%~KYB5Faxt>O_9(uz} z^J8A)UwCP&6mn{5CNFOdR%qcixv+SiEPTR(Rk+3X=D_mfFfsnhSWi zKZ{u|&G_RZ+Gz#(Gzs(BG)wrTW9kH-pJzt$sY5;praXqn$K>%2d4x)_qhJ}Wc$`F< z1drFFc>I9A|8E9PCON9j~g|QpJ8v&g^!v9J|mAGuVeAG zhH5wo;S;tVXX}2n!fRD`I&n4}>j5dgzGZc!i!UsN58={TUbe;(BzP^nC9&27SBSM$ z?BKT(!64X=o^&rSMda5M*;R>rkC{#Hb0Y1E$nRN>XpyM*j`Gsfd#6}{FM&Zs)-)Ss&y(c11QskMEP7U_vlNMP@E#ghoFER=EKSvzE5SHY3@Fq z%-@h@OJ&IR#GPp_F%FY+WHO0NA{UlC)Gkwz<<+pOGJH)d;&l9DbzkCkqQS~9KSJtVk?iLoh zd^^CH%hM12yRd&$ovH@xE~VNxs%Gd2EE#9kF)s{G_xSTIFROER|x;BY9S zQG7`hMcL!CYZ(YuUzx-06o{lAA$tnw#gal=jHIuD6u~h@c2_-#H^~qz`ci}?zhk1+ zbMZ|Wq~R*ICXT2gEGdkOlW`kitSosRrvf=yasW=*!a5wI4rST@8upKA$#H&iv)4-6 zg7Q(8{2AdwOTHhWYyx?1x+Xi0Ot?qR;_U9w8gm1u2E6CHicAaQY@Q#5AG>qh*pPxhE+L^X za5@J+w|llAQ{y{1pcaTic?T(%D#{){L-`6uamc5WKPQBj_J!bmUi3MoI0piCj48 z=cB=?LPXuhYztPZIMZ(0(+HHSGWROh)b!!J^|O@MPQLBY8$RFD~=_x z-@Xo=gZGL9^&#Ua#$RWO$`ny{8S&Qc;1_qwP|~HhkljzRN+64_Ou4jD#u*EPW78{S zZv&gKeY&ydnRpq~Q3bYj1|tzu!yUFHv|$JlGd0LP0oP&;Y*Jb)n4W(pU@*1{cCO|| zDDl#tawcjy*e(i|Bn?I{PAGz<@psfdmu%5RJQPG#ut$g3IRl>{QOw4IIAovqy487@ zV#>r;rxzE{fTyd9vM5KyT?27AX50mjcEP1A0aroc;5{&^xa%cc!Ck!H1MWJGoxR{P z`h~j(vIIO!e~qI2g+-NWLB0-J-}o%8quDxEx4O4X2#dEqe-9p*bZ(tS2KLh!zR>eE ztp73p8$ExZoGIjV8#sYFzoLHZWuYD`)W`9gIQbl@pCokwMSW`QgA4Qm;_dk1FaL6z<=!8V%X)g*x85yfC&Te`b#r z>@gBOU~IL{mEqGH;UxZefqv4%2PAWFDgMa+JZ!!RT8KZ+KPUbeL1MpM1)YP}(C>~v zexs}aWnC?@u>3kO*_FnmeKXt7UQH|V<^w>Sf0Erf|rjS1QCES^Gvdc7wsc96wr#o}+kQ4`8|wR{+gB#_bIE@wG306yn5 z+|XG3cj~mCEb0pjdoX0T;G9J9+hy9tzB*wf1oNj-xZZ6Q;YZl>;#JhvzFm6q*2zp1 z$$0aq8;NtI9G594b* z0XrU-k}69rhCe@nj^gVgxWd@$Nn*df3jYLemWb1L%>6;LoF?QOMLD?oyNPb^3Bef> z#0f!KD}K*!F!oK`wFzWd-dRU9_TiEkv)w7`V&C)9z)*BI8#aVf((bpd?+50Hwl>*5N& zu0dkIT?w6ot>7~hntZT5e*M2ROCv&V4#?u_V&mN26M|F{R271VVSTWHD=LJt+5cnh z%j0#bzVJ=2`MQ;kq~a<=$WUfw%Fs2HWKJY=sSp`Tlp$Pi$&f@e3Z;}N$t{YIDVd5Q zLk<#>PDdsgVTltU$zF zW>~kX74Wkt(n;}!p|}IOnDqT7COj}LMx`3`^Lxla^z&1$4=%Aotw=Ex6#lTT1r-v8 zbt43-H>@T6ezvSD;Z`m*F~d5FrD@DM0cGT8As-;p0`h;S@BcciOK}D459^93C*|s; zYkXHDUA~J;4ePeAz@1mZEpl}_uHfqN1V^nuQQX@-=rV6uXTirKG9RYeogB zpzinO{W`iIKdcW|4+e(N{fWLp=*XfOv@mDuXOPb?GpxJS2)J7mPmp3`4n<50sAJsy zH3|_hjUI_V1hV)SNJDh@MEqT@$jUwqC&dI&SlJ-^a>KfWuJUJZy(PnjD{EKx{%o+d_ z$)zfp)MOT$WSAxgFg~12k$Z&`K69`a;%AE5lW?g_F#_>zZ$+0BKK*fp@EJgG)cWoV z+$#mgV#?*m4pNs()NG1MGorql?)rPK20C_}0=v~L_Ox2D`&A>0V|B5-PL`jtsgE6D z0ds1x#bok6{6pX&h;?uST|NUHm&=jbP~ehcx}mtnqj(J!H=?HTQ(=m+4n5oniT1VVl7+97Hg)8;_T3HN2)s%xm*gY7qFL2iU=t1+zOOHj5_;$Sd61`Re0%cJNLpez%C0bD^5G$3UPWB5m9R~2<&I*f#9~Y zL>{Bafkxy8WJ5<}9~5iKs%h9^@`pvqD{-k|k%i)xqazacClgULa@tIwx1h0|3US!K zZZYN{hJ{2Or>Hy-g}RI{H*Xvwh4y(*83=WPr~@&5q-e2>>_27j7O(MobBpm0rP-Y; zNC1>`1)OEmd2AZD)tLO@0<1lbVodV+f)?#tWPF23Wgot;3>gYMY4a~B+kle0uzGe+xKD*#@)h*A}0M^ z+3DBDck>cSS7HiBvCtmd^mcbZC_PyJ;_v8BdwW+E8QF<4>=WSSp@-4_S+q~+6BIc) zSbZ{~on7+_p6Ccg;XbH92U-dkY7wDAFP%eM+Rp zibVmroE7={7{-pHe+lYeitTSl`(##J@MOS>KP%IPt#~b>j8;4n>S!5q9>#BD$Lqm) z0w>I{(Ssm!7TBl(xV5eML%yDMYfwu~B9+NF4UDMq_#{AaG)GCkAIp6F{uz8ND+^kc z(1()=hYSCI&F5GL$TTO-u)T$rY(T-Mu=GGAyflbumHV=XF+gJ08$e4%AsZ3-twBCN z&_!;bYbhk()!vrbM2>k_dfY;vt`q^mjtYW<-7mWXzh18;C|{-&K}r z&btc@Pi^Q11I~S!uI2%Drw~zFLZ36xjz~3tW?=neptpvg?FemWpcM_Y9tt1>%^8BW zC-fEr&0(N}qAqkdH1e&}fzYf5`Xfdu6!`N+7rH0}?MUd3^D@r|2Kso03mp@J-cRUz zfFem`#|fb`k)>mINfX(ZIIQp|vf7Jqsflb3{Ad3OZ8VX+gey#BlL?Mm`Ow&IEI&H+ zT@?mwcZ#YfQP!3Lbnj++OKFaHr+yQvCs9R!irY{|cc&l{R77jT3j6=?yluL+uzzr&OjW>MGtX; z^ITN>K3vL0KOvayL9mB{Zv(F2qN)Vr_dU_rUWa?$;^KC?Xfh>#{Wm*^@0Yjq_Vsmh zDsRr^&9GW}ST}VvW;iCAhW(TvT8xLBjFcS+@|ablzvHJnC}a+KI)ex3LI!<}nK|YO zo!3RzCVC#xl?>W`T-+Tnj=()k=sjRi4Add|Bcihz^ydcMZIaN(ZW8L;fajjYr98I_$<1DlUdVInaRtwHBRFbxLSs7>!QpwXAw}(@s5}yd zMeXKCVJI(&3$UL68{6KT?zu0_ZyjJ?c&c)X6Xil4CNfjVNN2bau>ku#{XF$gx-Wd? z%^bwetSgEmqy8+$iA}*z(e8<(V~TVs;do>)7;z$DC*p@)D8TfQ(Ou+AjK^kIpN>2J2$D z`4BUWzk&25q{`K=p^k7}4cH5~)CSUV4$>{?rd++(4AOoCN3EJ@Y?q)BY_mE`zgGC@lWGwoI>&$JLkA(F3M9sFoeE}=*>b$9*2|7Q|@Cl#*!ZQ z+^C%GxLXuglVYNw$lup>_tr7WwxdvZ2i^S?h7R4`%ymUN`&5(^O+;bkf$SEn)AYPW z*xgp?fV(BUG+U;cmYXrwjk_PviT0OJM#(|QGDIH2>D>QzH)Y3f`opVnnGcRU!%=C5 z^`EF-VRtZu#eilVtQoL;_ zN<8fPc{0Wr62wf@zd=7w!MLZNySYAS#tttD(tYj= z2Z#0M;=y4pbZ?^1;b0tUy)udx<_m{yH7zF{*3E7VxLXttlVXXXs0wvV7N3bR2B!Cs zqk`^!8)=B{9_YH_ZuV&)DF%qb`UzIJ+_0{raCItN2_MduHB8Ib)sn|OV^O}uEE~$m z-9nBavH+0(+ui?pSQllPWQKJ!WFz_dD7R7kVZ9rd8rEeI|8@%eB41z6(GZQSAUKNW z8F8;G?s>zyCCxICD&LQ19OUZaJ%ip8-~|F|2@o3AzZDBag^*K-yh6yxqGvUd;GNm{ z*JXxvx3qwtMKO&O8}aN0LZtSId7|rsd)c8mq?iB-e^_5< zlnD>(wg^;jSWEakwrnZkmOauP*0Yfg@%@Khj-Q2GKx8Q(|F@t2>#(lQ1*bn-4}sU^ z>c?5v`NR4_TxwX?9SwKh2xH6Dx8e$}=6HsyZ%1SMNjkzC*7wmgpHl6|k2$`s+CAVv z-CxH0_vn87us(M~FffG9B)YiJk(DFdVZB+!S<+!WuxP;DqWFpwzZ{jjJ3}4g?oQ9h z-H-AQ0e5eN3plJ_LtJRcwPv5zlVYYQtotDQa>Kfp!qpkp68-~Qb~P=pRZ9-*53xrO zv##vn$PjWnk=23x-|qge!y47nl7|BJ@5sI!q@2x1WR6}khxa~rdtRb=vLC-b=m<4C z!e+0SW;I|tlV5)u#&MU_5y!ycO{bzbMv69uVmtIQj>y2c!MHofKLi}n5DuUtu6B)d zKb1d2imMF8WRGH>sl48ZqsZz|e2;F)mz_v)N&UCg|9d=&C1&(@j-$wgbZYT}OYs0H za`lB46AeXvk76=LGdgm6*KkLkawwX)6rD+N1u2>sigj$EeY#XsOrSXTV3?wYLy_C1 z=t7EXNs-e~jP)okVD1COv^Xu!peZ}Dx|?GQh{%$8BPqT<%zdzl=!ci70LqeCjyLDx zCeq|3YUMc=_ieRxKz?83sc(1p_iE-XxM1vI5(xD*5BBQu>Tq+<9EHX7U8anCzB zk*JCkwHXgsIwvPnU`%MU&pSC0>Q!6z$Zv1oWYKW@pdF4* z)V3zuKB~5f`}cawApE)jmU4FC=)iw;p=sXD09ZZ z^^D#tSQ=_wm#z04QfK~RMHEfh*pJ9a=3swo2%Woz+nmnE(0v%%{>jM$S>k(HkEG9o zRA2enV3z|TA$8$E<*n-ifrTK;lG&UsTd-yPIS^F%0-Zq@RP9=uQCwhT1oOfzpkN?h z2=(wDQvQQyQsXsJ*0CbBJ`2Hn5Jnr-qxqV5#pKuE@}!;Y#4Z$_o#Xb|UHB)RmuF+F<{w)1&bBZTR6<>rBIVY3?B*D6Nn|E&L;Say4(Gq>ytAu=1$UOr z(G+6umy^dK@ngjW#fm;fbzT8l>IgZO$V`Lm>>($j*oaw=g^BI_As77v*dr54UVA;Z^m0+EFba;b;RkGUAn|Amkl zME?FO)A|zJNcWb|>hDC}-GsXcQt}4pOS~>)sM`#NJJp(gCfwmYkhV=s4`hA{H=#2)t-awDR+y?r62)cmKv-{Mo z=MiUMJ&93ZpmRge#e{AE6vL(jXBM;aS%+Mp*=8Kls6X3O9g0iMHa0Y{3&I1M*?z(m zW}Ev7j#?AZ*zP6oI1jqvKoHMsP*himvd%**WHb9zfxy5PDwC+&flAm>w`ReJN`~5? ziCKF<;@f8>8)j3(Z~{Tk-o(s{gjKGOGX2}Ig`2Q+2vCl*q?7A=VZ53{fI;RM!^~z1 zm+vTI&R(V~eB5=TT^R^2wfOJq_;|6&YN+1;Y7yyW=HW3ingX287V*Lys;|&#&34~1CHfm zNMw_!9f;tX4}ozyv&o)LoX8?wdSC){U`2u z9U4bb7bxoYpD7AUfREb-Q-A=M2>4C_v)t}&Hpd5F5r|A7vp)*t8$w3v58$M-5ox2# zaO$6QbNnw+IGI=!5mIzE6u&?hlM7p8#DmF#oq~_swLnmCmbyXq8;Z|nvO}q)xDFI% zxy?+zM>CvxC(U~}{_vI5-`T>G@WO2Q>mHiIny(;SgR-$Aju`O%PdjHQ30Z{5Pl1dZ zgNbWvMgk6j!XF1?)c+CM9M?J<_P?!7(Ecy7KV>MZnY4;r2Q5@u>h0weUf~xBv40Kw z+P?);g_>4i(<@BVMg3fdJc+Jd#v$EOX%ojGqNqfQjk^_zEufrnNOt4^IHVK*5Pbfz zy>ZAy*I1L-fm)=PU?}o>6z$D<=tYX#4aIVgVt#*VakN#q zBV`?me_&>HcfNMd*G3-od^lJ zUTjmzc5x>(3qPs{$A5sG#L6+`zBaG~_ZY?x--r4))cj>O&t&tA$eLH_n3U=dDr{as z>EPB3xOtvtbSj3beS?dfx;&18Q3K|hPS)OF#j^wH8EftQfW&21=Y@Ow*_1%A&0w&- z#m42-BfM`E{AHiWEc6J^Y?(p!AqE+{6ddRI5W0-*-Jwp-CF74f5_E`JQ{ZYZ)Ze1? zMZ_)y76z=11+v+jDF|8k{a>JEc_BY0aukrTPIk_Tc(1aHO!qU!ZoqVzSX{cM`{&`H z>2jEZ5yy05T};;U)YX{odz`CW#&nJI2b6!4%74kmC$}>g;!W4}o`C75K9*>@Eif5P z_j;(4tH?MTjBz^PcOc;l&vfro`UYYLP5 zb-2|2*iqzUdn0V5e(qt0jz%sjdaSuy(4;!}Ghb}hLs(zJ82FN8Dpz}NW6I*|z)(K{UPcLyv7fq>a zHbK7X84B_rvGwQ%xz#%ud#dxrc(%A;<~x-;XB*n42HE<_Uz^dkiz1jq_2< zgdl&qc_7FSL&5m`a14%RkS`DQ`xqIQZB5X@FE|ULtU&e4PnY6IWj2dLIgA^AYS!?GdEm{7$A8@+^^!6Gf`vJR5uv$`qWj#DeogXr359982wQ z(0`b^rAft~Ql%V^LD0|NE1wO=sWdbzgdAj6#uI^;PJ-qn^kV~UWuT)TbD>>B&|HK* zZ=j_Ov>%e5VXYQ|<|ee0fnLCoH56#Wfu?>tx+a9IMr3V+OzGxIe-C3fW*vv#e&4GTSrAC1qDQnHq?Ee_t6`!BOa75g(7 zL>@}T6+D!i;HWhejqUu34`*v_3q90@l5@4Sue{Fw z7DoqOKnnCcL8rcxzAqtmD#s8+Yc;6wdryJSZfpMM6xJXHus30dWIRdU7l}3{Zf+z~ zy@7lHwuflAz~|jwMLf8lck3wwV%ugrdo+bS-N9o%C4`f2tF~0x6rM#Z>2S%}qL2o& z*s`oNu=1jbd4PBb7H~1^CupOTAmnT!vjCYe0=XlDA1m;`?2JkPPqc-`o0(b9@+aop z-;g?%jSD7tU|55I2X?bR3n^>rdKtGlw16YrPodZ5<@iR0?JB_>p;jNWRcF)cQfH>O z?Xcnn%)pKhDuq9V{xKMQhlt`6Qd}nrIb=FigE7;4$RR5cDnWI@ND65%ZNOCXP9SYV^b-;qDrI8sclJ|YubA}CrJZ_*} zA;gTEHZgMRV)g4*rcXT(tW3x7z{;yk#kz;AAFSm#!;ccLwOi?=D(=a26vxOqX8bwI zAEfd&8}~=!gvwM8cS4ul_2s*(yHcg$`+|;Z*~l0?4L0$6d5n}rsZaPh^q92^#`d=M zj!^s=V*mV>4vsXXMNIn5g|c1iuS^=kUw?hb{gLs`kIN1~Sz=d(HI=fu;|eJ&$_Ds7 ztC6@jo|cBKu--6RClYyS)hM3TL{qB#s6ekBs1IP>wpca0 zfj+roFwke=*aOZB_AoD5SFfh6T0r}qc5h(ff{eH9egASWI$>@z&I+;V1gB{z$0D&P zSw~LSQJm*@x)hA_-iTW+!D@s|bS*infiq48oP)~Ej{M`4e-p8Jfra@dBMTbyEo#pk z@j1{kypSb{-1m);y**@O6_=Aj$WlZu1rm0g`@D=?_a__X^Aw8Tm!zG{#NP$k}0B z8u^D%C##Y3`>zvJ@Mq|5D2OmIg=gp&%&RkIplM2~N1|~cLd;h}6Ej2aK&b}5!u9fi zkarT_W zgM86L{;bd$5kj^i@*N=Y8~|>3g_daU;Anh%|rPAKp z$ouwYSVL*=Wn3ZcO(!^Ny~3TLo9J+_9+Rv#ly$w4HPDyUAK@%nldzz1W#Q)wp2ek# z&>_eGb~jhn!?=PhuJ0hL3L4v=;-2@Uu0*w?sE<~%Tl|XKPP^erspI4gVLA{Kbugj0 zRDl(mDgCXr-JKwwE1@EH1l{of$?6%h&`Z}C*}G6vutv(TDnNIW827+szB9Y9bvCpH zdVz<&q8;7-aR~V!k-NTl;GNEPMndjQsT(*BsuWq4s=S%3o>F+g^;`NY+)jf~*XJ zqt^RqZ0CZku)n%dR8}LZgD+|>790{ajhiQqD0FKqF4e6E5bt)nE9xFxK~!&o@qH$) zU1rfG;V|q$S<}9x3C%lzH~&F(_JJSMuX^5#kO6=sX1Ij0u1RMbyxP*85`!SQc$E|xaBDZo~7foq;J6lF>M~Uv1 zj#_bN!$RJjQ|sJk{+%YZ(|JY}wo!k|>F>xvrEllZIhOe%Vs899evOR<30BqI+H-%k zgnhx!HX-U4F|B8$a6IF^Cp?(o_h&HW+W4@RW;WLy~-!jkc|z5h4>Y zI{ahjXL#iwJ3o#=@1;969m}ROOw*dJG%R7O82;rQJ7aNa%%q*s-$mg(ASQ}&q-bj> zc0f6kqDM3I@O`mb_(R~!2#s*f*~@ahn2Q~lOp1brVv0v`Wm{3Ksv4%q=1^>P4VRY` zGfA=K3)!HhNAU|f0xd?wQG5yM)Z#^#A|ENMcp=g3J;PJAGAbSmj_33p7I5#{1=}`pU>kne1HXIRn%%;u z;xP~dE}IM^(O3_KdifU|G`2U=&R&+5tnVmm&F6}QqQ0yKD4`{5|4?5R zX4M~XsVv=!vQk`G4UH_GJ404ZG`73qo|mO1Y9mG64^hj|Nd!W%${L&dyptQDHWO9V zC=_8NW;o9rpR0lkJ##!PO|{~Owj`LutF}AY_WUyA_OR!$RAp%xUd6zTwJ>Z@wJ|_- zD*POzC^|*Bn}qW~7?;Tr)*Wu6ZaC+*Vk{{*r#B9@{h4k1N}0%CCbCoNXn@Uz%s^zn z%L&KX%skK{7}>{hxZ^E3q|h%Uy@m>9Y(u$k^E>VdF~u9Vod|^WRg9{mY`W*OguY;G zwLo9c0~6Q}qB{ueU{J4s9~jj9y=mV#$4QtW!ng-<@jJ-ytryhSQ2be<9{?J*OS#WY z3E7)7C8Pi?ULnsDS=k^DD9h5yGdd{$LsK9550QC*L?1q4eu$<#R6{0yuB`40J;XT8hv=moUdHm)V^o0r8aP&F#1e zr*uUO(LPoRQkmn$QvIP+qKP}|CE+Zt`*^9vf@1V4l!5wmiHkX48*3nX0i92Wq_RlTrq zk^L%Q-RRq|b}?MaevP4m-5++B{c7L}_RC5ze%Bg}?bW#F%}ugSRf_s@u|!?ti@LtA zBdXxzK~W`h;8LPaBLwZ7uBbz}f~eoj;&LyhQ@f)?1zlBL{WqfC#}2L2t6vdH>Q!$p zV7#a(&-IK%Eouh3nXra>^(L+$>UM&o*4t=opO8(RXL{AEniO^9V@8EuvKam=Iyk=3 zKJPg!p>8MYYog){Bs_x^A1{&}-q8BE^ZgIMa4Ww=;EA%S1Uj(Z{t-rfM8RK|R> znv*V)SIo*=J{VsONLEQ?2~Tv_<4B68WZlJt8d-%PbLUbmR61~~b!O9Pjm^K)?6+`Y z6xO#9MQr?t9ygD1Kd3_`{UUe|oj=7bk+iH2otvN|4Ith;()}yqOTRN)@0MUsno&$o zh)FagPFJok%T74!gIk#q+Ynz(YDF4@DR8<{otHda*`dMhBsI0_$W~cQtJfQGKH%v} zX1ZpE(219MVx#pz1%i``MbU{AD;CinIu)r2)zHDCj5GXxVmVv|j=SE2yWG>2!ET2u zvjaWJGsx#TRYp7mnuzBnUIlo%kq6UWWtXEGIUXm+tv<&>!%+wBgf4q;4s#T9I8H!E zrKsxU7($NYAA0@iV>oJYh~m2iaU8oLpL)FKa-fXBQjr|QYEyRa2)HaOJRS!5jq)+F!v#jJAlLNEi}NloUmO?|bA z%)rirlM?GZ>ZHVrNEd!eto;Wrl@eFqjkGroCQwTJ6jw-zTL_L?S<%?uBkwp*G)UAu zirTS|>P0H}qTa*kRrcjRx-Y8aC|pX^Llkv`E2^~-)kCSsdJK*2{u1RRdWl*VTL5%uEb7HMkFt<^e8PH+X%nv`(PRpReSsM-HZb#48`#Y zIdXs_q3Gm8wBfVg467-|p-R8a&9NSeS(8gUfhw-g$o1L#Nu~nCc(0OBNyj@W=sxC# znAJMe`g67(hSt#kCoMZup7>H>K2Qzt;{*8lRNP$B2}X8u^r?EmF#i|FJK^pvCuvEM zV&>UkuhU@^rWpU1q4?)J_s4~JeFoOIY;3>h^d~j&GgNMn^D*O$NON?}1o=Zq=)oXg z1wSyz!**Iv-bvt18sv?Qqa7z9X=TaW#s*!`0CtSQ)FxL%>M~cP0Nk3k|-pS-`fry*KY4Xkc;!NI%Jw3?AgV0#j#N|!?<4vx~-$eujO@0r8iY6}> zvddxe-XNtCp2@`dP6-Z|MourVzRr?)iVc3BFOxS%b!kjKxi*bB3vd}x$kRlw0x~^A zCNC;9OQVAp`jH)F->nmiv?{=UgAoNjngE)~v@ zw5~{H@&h=NNMiC%I5uN9y+q!IJDo%$lWP#$j~pH53L6_dqiL z31LN}F9`KD2bt&1qh%6|?jM%5g#!~-pk049s+tK?B}M_VbrhR*Bic02_zDZFdD#0z z{fBUnM})kB$V$oOsy^W}1OM%zme7&e`!Io5Zz22R$HXXU&AW<{v1zQgxTgLF+QlsX zuCa6yvKW!G46>7lT%dSr9zv!OIlv%q^N?R*K95=a9c7=hIFac<;yV~p%_-_6@J8M& zhnw)-sCEos9oDo&bZV*^fil$CyXzZKlkqPe8P?qz^`d=6q-Xjy&AnfgIuDm?Bg1oIj zKwbk7*lmqGMy+{dLLw_rWOIq+!N68~@3z3G5Tp_zWgJMz-wa0-{_uCRx*%y_LxmiBm$r{%8@mgGZKCWB~lto=} zC2<9DbJ-wjMASZl- z3fKM+R#ESk;tJxvB{*t*hQ@Yw^$vBa7sis;i1N<8#V&GDx8Ba!Dz%)NOPITe*(OXv zPD`3wP!1q!wg>w;F{{oE!TxliobHaC zpef++_kj<5iYbaLqqr!+!rG4u3ztf57plSc(_tIM#UHprT%7F=aMWsv#`ZDVO)!hH8-G%v6P(PI3dG=_~`ZnM~-8O*J=&#~$3%~psYd(PdQ4YK|F4D0iO*0C8RRw!T>yU!qMN1H*qq9kVx2nI+PMrC)A5A=y zB)jLRSNE$|Ov)?kQEFuJb?8~(%S-F8H}%k~_`Bwh{-k(^6t93HW_5*AfYXfEd@ET3P=OtM0HAE)C z@86=M^0i=_2zwtenlsKMf3=`ryx&`V6tk&D>C+E})O-||QnLir+>7o>%|b@adkBtN zmC)F(oT%m&%D*L~<}@_Kb6?j4)!a&0B)OU!Im<^=O0Cp%@g)kCKx|b~9~$B%E_}}k zVdpJRG+_+D5rZFJGRQVcnmNmluR6fQJ6Bm@2_{L;zk})DeQevsX&YzE&6XQqwJRl! zuQ~`9##e!me-4l`KPcl>!0@YrqF0}%v!1H~6J(?`L(}j_30H0j=&1Z~oP^6~vVT@H zG&B3Uc`&Wu{hvaP&4oNci7iXS%H#|(}|zXFCgP9olk)U z?4{_G0%Z)Y5YNBhE&^pR8ryjl5Y8JD6KL8CR3?Yi#*Xs(f`Or>`oV zJJa9Z*psXXWwkT1&Q_qexlw%);m5!UrE&ehvb|uVIGh4b9J$C*P#oGSdl6lR%L=n7 z&4{eL3Ri)JZB~pH?Np=C+K9eufM?KfSCZ$u8SJ-s?lL@!FigNRG>&H(B7i|S-sPA` zjw0lE-si|}I5ylOj;e7SgB*@VE=QCcH<6=(&+#Q&;d#=E;y86>xIec#99dnC7szo7 zIbyGPeR;}obT224g>f9m(UyH#akXQQ7s*kT9Ls%<>W1SLIyNKHCys-0M2?{@$0Typ zA;(~!<1|}kSozC}qhuUM4~L_w%kdI9?jlEJaNzwPsNijsOy$j%yje&BB9CDk!x>ly z5O!L`{D~CFV09L%2bgNzXZv5qptd`}&>CFhaD{+f$p%sDO%T`%>4fo(_IV3ciEKrY zZ%wCdBmZ&_+>GU26v=1%2O~qc;{%V#^v0#eaz%3N4GIT*EC#=S5^CF>ZJSV&j7V2l1as9xvou%TR3$W5jYd9q>!7a?OWs^% zuU{13y&fd}YZ??XkI1|NM8e99ry{91<@17T3WKXZn=WJ1_~$pcj=KacZ$g*MV=^_- zrC^?!fl%dm;5hNEGmwnE#2EJg2lh9w2n6>W%72FFnn1&N>#8z4(s*-JoE(8<@d`PT z$W$PqQ%oV1a_$=1IC2E$3C!|Mu_^0XZfu#LI*fSsK*`&AQLgZ+A=l&8r7$Z@{JW8+9{umtVpVr4#rbG96@;}l+xsF%6OPE%t$PtL#jA$awLvf8;GZO=+8xLS}~b= z?ns=G&yA;C&@ea>Q!!E)PkTchUQEWHUt)*jG{8nSeyok_n?dkD>kw6n_#rG)f=pi% z&`uS|3Ua*!F0`qSHs)EXy;ywX{qOvanT7n4$X>~$vgnB08=`3B-_Q#HEXLzXN*0~Y z_v_u)HSzo3Fo#!iucrw&QuObWsC(r7Jj}#g>HJxVO3ngWu^{ATB3BvYa~^WuZA1f#Cm>s-1A2*R@vtk|Z zjM|*2G&S?rX0_~B#uad>%6MZ5jLefzRHODwTw&B+L2%SsR}=RdGIqSmcmv(FkFsh@ zW%num#;5@C-WP1*`)WU7g``r#s+pk-Y(M<}G4gw*_lu*U&YOb1VDG9sU{;_}se#Z_}} zc%8AuU1y9yc-e2F%d%#FT)~=R_lK5sdd%(Ad5wq~>O-nd1q_ zPYTtPK+5>`Bkni$&4%9%BDhBdgDu`BBOQ0v@mePE&nLxzW5iR6v%K828Z zh+GCF;{8e**vz7v+^$CvkbyvY2AAsk&oHf>#qIiLT%qd^5*)Q&V%J+U5dcO|PVZ%veLAMgPMWM%UaMZ$~ zji<4aXeG+%P8sGQ#B(?f(od;vurKnT36G=VRiMx*17@xK5N;;fVOr(?9kYJS5$s4c z3W<$R-jT-C)P!<3WO2pFZ2`YE&nS5lE>&>7S`@yi3j4}$6LAHCP?ZE90J55tclP zODWid3QmPNrQq#G!3_lC_k_^cwsFr>@E0oBf;#LU#~8M@BE1+(R)TOm*OJ{aqmcIy z`5BN2MH1p6hLP-;k^5^hV*?DLfR16P%6|EI+42QcGscz&F=^uc4_8YedlA_e$Yi!$%vsii zq+Qq1vM$G)uVp1%O3QZC@=bJCwrpawyh?-9dJm25zj4pg@>govpR!Mmm6k)WXfRsV zk(RG#r7cs(KbRM%D?&d(^eUojrhJTfUp5=hLf_YB7%rvFy6YhEYFC@(xPr|(5gfG! zv1sTW)aD?y8Atwyqz!f`Z;nx0=U_(nC-DBAxR11e2i^Ehm(!oAOHcrbPoNhGx-S2fLdx>2HwXniM+h z#HHq?OC@2pmFSurd=ghM=`w<&)>UY1TZ}hvUXrZ2lvTjU>gmhcjj<(J57+i(VN>dU zT*`f~QdS#R)_%x)JNvOD7~iVx$81|)ZQ~|2O=zKq{gA`PrZJ+w1sP{N>_~0Al*JTv zVp~eK)1x@>LQkT@%Wq$xXl&$IP0@1_#H>l7#-FkAQZz<4s$uTL1o-JYngI6|^Cv*u zJjImjEQHG!4labN?e1s$LLSk0LDFgZYP&e0-ar1MDTEH|PB3t99p}7dg!7ToB zvopfdq~AE4`uO^3WNjtevtXleFgywd9J*}M3bGQyMHRQ8+X!u&OmNcQgyyR$e}rC5 z(NhS&1z#106}m%`GuqDMR6!#k_Z|3~m%yr?NAac+u!ZULJ{VJ@ZIwxiN zLqz^_75{~Yl@b!zA~84#Ok$3bp@?C46-pSVw}i1lloiQ6==VJEH~s!20z~Hjojv)B z6gx+3MGt>`*NDih}?jJBk1Fj@GX7JpZk{iPp~J&NOAfZ`S{pn z$Flv^;-HTu{ARXXhL(PHR<9N?UK_5%_eQde?Y0t+U&>G|TM%0rrYxG&i z$AY#YbOE68Q`LVP#~8!OO5e{otD4exJN_vj_r+So_i@Pwa48?>zY>0Y7u}SPFI^!Y z*CiO=i9uugU)=M?@mX4?JC#236s@|!zOda}jp=4j-rU8T@teSyM2b0zaWz&YD|%fs z6lexi7A7PaT8<#5XWV3@T00NpZLUMNc~`JFJXAjV#S6@<_uh#pCF&6L-%!j#Ph zgE^p0Z(K^77$!e^E4n3ZPT>mLG$lA{bwgvjR8X4>)MhIA)1(b1;NSiXj7i;pnfJ5c zzMq^wdS8(N1+an;XeL3shq6nNrwX{q`QFsaCFhC@$>0oJF}y~G8DPNo9sUB3SEXH| zlJD~FQ-=SCGU$#8^0n7H_9%8+&>pp~z@@RrwdnIIC~xe6E7;@DTV;<7G`0)DR$fUi zQS&M43L~nwFUmp^(kb|cn~f-*f~RNHUct-p!|h`gG16b5xcgjj6O6c-L`1D^h+O+! z+SxsHj=_2o`5r~SHpE*6bUh`M^B}As3kewp2n^ixH2y>3c+5N_Q zB#lq#+P}{giNBN(&l2+72A;SA9%%^Qgt-)|C^D=em}i@Ns{y<>{w2aggGgk{NOov2 zVg;m#uNm&jKWx^7;@h2a01*1kPFaW5#ip z14Z)(mjgFXPS(dSNPM@5x!1SZKE)#eu4sbwlCvb}fk^a&?IMG1E!!7J>=yJKfo_>8 zWf~_%mgMMJux>aGcW_Qw5$fxAq+I@F5;ah^#jJkD;m*1wTXrb1oh`;Yr` zssC_YRRegrLC~Fqb{2VLt}*1yZJr`V#NT0~ya%2cmB>4DYHqX`21lFK$pDYFmW-z zoUa#o3SMAlxteUB4B(*FV!jd>kixU-T&mk~$L4|-B6K{U3H?vH(EE>zfa%zgbK+_$ zCp11|^%no;)n8So;!< z1sGyhA^6>Q!WC4q8t+y#{Lf>L)3L`M)>a&6yTjvbLvWmZ$f9`wyds;tfh*W#ff;8r zSzoQ8$K1f?1TT>_DDsPbv`ge_U*vpjw#fxs@DJAofULx&b}!Q@j?a)vTrDH+ErO#~ zU;M{zXT;%kGrp4{S+yvuC1fo_#K8hrAEANI87~NN2N4yFHkaTdeTI0m*-`w1*W>Rh z%u)jXO~dro(tcyMI_1@r!vsmkzvhaY82`gTwD#^ zGKEBQ&MGD!;mQ9-xd-KMp3$^$%zFEn$wvc2eeFoj0fsYN&zSiS&PG2REv}{(-PwXa zHUML8!61S$=VN{_emDU&DBT`0&dJVA!xVhG0v40-%F*N`_MS0pp!{V*UCdpX#~ z@9UG~?KC?Z4ta#;Ov3|WL)jAVYmtwd#!36ylNBss(Ov`%v3XK!cN_IyJOj-RikpI;_JYI0pi9CV}YxGHRw5ussw z9R5-LAL{=M_5We@KRj$RtoLAPuZ#%o6)Uj}oDuq0QnThwm z;T(mWke?Bm4rIb3e#y4LvGsB6*MPP+Q`@ge5s|P+5118|i2HL4ZFz~(wy^#7%z%z+ zwwBE{^`?%I$MDr!Q@}Kj@n6Xbm>Xx2!6{(Gu$~MP!4R|B90<-zz>xM81FN}f_5Ipi8sI{YX@azGqO7R zvUZ~Em#k{6eZ1nac4=Iyczl6LuZb&bq)B>t2##8>qOtuN?s*$8619t>ruU-R_>SF9 zyX?zS$KSyajH{d@{Tx`ZSYSp-*wwI(vzumFgCZnmU4)kvBqIBTWH*s4VF}h(t8JzD zYf-nTH0$id<)ym>y9Lva-42$Lb&GN`!tYR;9`C~RX}?D+21`R}u#XzN(UZN7 zoX75=I4>}ZlzZ4A3hD>zHMEVXJ1~WCZ&&3PG`w+Qht_X2V|(Le_`MGsP6Rhl*`>R zoSFrSu8R9j_Kt-*@&^T6?4GP6)}Vj+th95Y8=t*f+Dm5y)z#oWN45{a=FIJt!GP>{ z0XY==zk3}E3i=PBqmv0%tcPDe)#+{M>8{J1_DzN)C(PQxbqcc=Sekp|xa0_2D$IU^ zXY6NTTZP#!Tp`T55*)RPps~Fj_q;cfsDu>m>e7(D??rB_$q_K*D(W^(($Sb(D7$jNjm1h6?A-*;HdRCcbyfJ zQH3b#tB1Vx*y!Cfn3L^=C``m`Ab7rwC;6b$V1Rh6sdtVZ=Ee9%Y4)`*vFS-DhQ*$m zrm<-^G)*w4d6Hd+`RCc}s5PI<+=;jc zyO^I%m#Et*YOE1e>Tf-hj`SC6%=@Uu827o&lL@V2+hM{>p-@dV2hi;;qT_VD4N>`f1>^;0oMPa z#`m*vXQ>i-!7N*^>B0OSdGJqvUV-;!aNX~kXkn65A??0r!_vquHzlZ~#>OBrmH?wO6>%QM zRMa2a1o-Y3)Rcz=9Zcx?2NH#wvMcVrpCs7_$tJE6=XlbFgo>Pn?HzuNyI`X$w9gXd#@D`Gl`Ng~1bi!CF-B3zf7f?o^{^#HLF)lRC-+M-pH@lxL%v}Q z>NnXkB6puM#f`Jzxn>fH_64L(CegDX!gr8%1|68r4$k7;Zbr;<&dTP@APt42Qp%S| z7QQWOFT$m4d4f~s0(4on{MAgElL?Mm2QYKmmvGNZDH1iCqR!pV9$BBA;WVPrjPH8x zaN$i+lv013_Vu|C1? zadnd+en#Af4Dk(XekZAA!A<@<%`U)RdS$XWKOtvzahmnjPdILg^Ag0(`hoggGTEu! zaSDygPI(cBG{jFKl|Li>t`13z3q#^N=&-M^(A_l0Dz=!57BI)%$~;!8CU>UzHo(gs zf__8jQzDNXqvxY37dp!x$A6Er$0tYyu02jdePfSHI;(J;AITM}m`!Mw_`vuFcA!1hhg4oi{T4OOTRcqXN6od65 zG&S=-u8{bq5gfIavUIwaPW9I9_tLgMPEnlQi9;9 zHHOvmIHRCbG)dNe%6b;E5QcpI^|%6s5mFh7DMExhNL&Z$6jzVn_wTS>g^0k=LhC-Fy3%3{52NJov+O}d_8`2*hcjQ_tXMZ=|0z^Rpu*D)fy$%+ zvIArNm+ynd|A&-&+9Zi}tNdY36&qNNcuzdzmtD9$`050D)ftnTT5}8r&s6Zh(SQBs z%rPnZaf%bO8p57(w~#rBd^k~}S@K>AJ>Z(87)e|!qxZug$F2X7lQn_<&DijZk;Ayu z1lktb*?nL{jmdOeA(Yn<9JM;4vAqKKykev+M@>Ph{Ap`;4t2%wjlA!a47zXe{&d{u zhg;0g@1{R55;KJeRD_@bB8gmeg!zacdD*9bCEHtEBZhqehU>{t$uKN}62{rpkRw2} zcLV+q^mkGCng0F*ks<51V^>O%;FuZD@e@2pjs-49dva7H$2@Sv ztp1w*5J(yBj5m6RnGHXtPy!e`#85S;1*{i?m=F<8*%ymg84V0gL2J9L^10` zBJkWG>%URw1SRVZ%6h+*w><0jogmKoL6ACxj0Xh0?En+|4}3M_6(0Cv@-a_*rKd5Q zFds2#ogOJN=SV|jjY)O~$>N8+S&jv>1#^y`C9{U1L}4z8S!>}^d0%Wz$@a&+V2fM& z!TGb-Goo15G&Jc0hrJU*t(&v;BDIc;wA<@-(woIeAl4SIcy<*1XEOJjifA11lA zZ$b}SkhPq+@NiJb#1%vTX}lQCZe@?zFKK+Et#_9k)=kkITn zHbh{$I$dPCx~PENISn@#ai#2-?)QU1)BSC>_?_SoYajJrtmX$qR{@jEbhX9?RPRC6 z2eIkFdlDl7I<#Krnr?#a)=gp4t%AvDy2+tV4k70xaK@>C^$(okneGwFe~#Ghk{|hk zb%aS1FTr*iv$?q>^2h9XRE`?6ClP7(d+4%K#C}{MMeJ5xX|+aUJ4SPOV^*?8Q`Wh= zse(H|`e1Iu`Uf4Aj|3Y_*!O@X865Q?$auH3RxEt<@6k}}acn(Bts~uxhrehm57&kf z10LSQlE(3H-UC4oUyXwmsjgi@=`^0KwH=)}IQHReAkMrhW!jGpSomRDcp95#OVS;9 zc)+)=hxh%O+{63eF?x7WsFSad^Me)%D&RecwE_A4DgRAkp92da?Iar@FM1omjCk#MCyc<$^KIz|So)|04<1wov?CX1SAkDFuEuKINn4`fy z2E4V0YaAqEoPPo@dkDIO&~%YUT5^pTO&PjV_IPu@A4;;vvnW_xd#oUckNyQBtFhz{tm0%z$lH-G)tziJ-&qQ@^_@4=+FlzXA>Cp zVP9XNVKm2fw&;i!Fh|*6pm~P%HJ369j6A^09)j*9w4%r(n>iAqDWA2HJ^I84MsMfn z?Pm1lZL%sbKGqqB;|x*mBITYYG=~X{5r8BKjCxGa;4tkpF4$ z$C)^0Rg;AsU7n#Oej~Oeu&_kh&u(BWMTp@07eLDpLfS-@lGc&2+PY7f(?o_y-yIhi zU2tCL2F6T~8bi$Q7W9KSkC1a~y6HUwV-PTLTEm#tR|Nv&Dy|;lGsZhG01YuHr1Ejn zKjF}a0wcrP4ZXaT)@nXP;XH1Trn2ys;X!4!m^e$el3=5BM9d8KEF)zAme^SLLq*w2 z(DQ`;b5|0tB2^_he8Phyp%+Qb8tm`j&)dNaxwV+rF33VuKAN-Nho{^*8$S~F8ZNcs zI=Bn-@>wXWIeQ1LFlUb-IEv@zaj%(t?i?UJ$56;Q1WGrO(pYij`-&ZPPS12dH}99k zeSar+$54WtWtl)J1Z5FPTN7tQgct_ck`3=iPF=Ti8hG$I`>pQf*Mi%P+SuH+n1K+Be`*ewoFUa2MD| zetE&Hgkww`QL8Z5MvHL|^N87jkf`z$wXl&467fZqJ?n@n!?5tnwj#Jx*;bRH{(_1U zRnCaIfL0L2de}~Gbt_TV8I6v?n&zk2%<=1PUXQ;E z>n%Pn;5-uh!V``pxmg@F$+5E`e8WYS|NJY~Tqq90@5kt&z9K9=xP;PySa*ogcoSJ| zl1%^^0HMtsxVzR0{@FT!BFJfuC0fZ)^SW%_OwA)ta3K~=X}D3bvN4e35szcBSauWJ zDvT+Ak+p%lOx_N%l&VM8GYu%+dC+3I*@}vLq)m&;_I6&31V6~eGRT^fVX+v(-GVAN zp<5=bYocdLNmzV_#>OOsEtBGdq0Zhz($0o7tcl8~g2v;{l4mm2=)e}Yparb?1xgfH za~fu6S~F(th8}W+p!XA+RpgNlrh54NYgw`Z3WPvKeuvh(=1IjND71V_KKDS-l49*d z*7xoVSh58{42IywojEOSZ+`{2Z^@U~h2CW7BZdS^{7bFpl5Z zM@V|LAq{IHORoDOsK#`vF^Dbp*Qf50T39(bS>pt14`q#KkeLHR`EguoC_jcUw9CM( z8p;pi3fcT#f}_^QXlxIs$-SX0S%WF-NytKv_)zT8A6=K-48_z7;f4}-w{!}d2Hq}U zYNK}{&>uTTU@yPTKG4E0f4dHnp=kjI-+U8h4(_uEtI!vjpji#9_wH9N=Y1L8lYC8c=9hn>jt2vh*%laxfaYV@FGn zOIV}1wycFNm;x)kqr^M=V&Z&-oc+b=*s&l%33iNZ`^+`T0Mwca8I~%+skS~$L6cnR z`d<=eQ9`OD#MxPUVc)>izHeWrN#?S}&vj&yg@_TvW@A}~#}pHRmq`SjN9f0Z!X#Tc zUZN?d8^|Qv5Sby99MkrjNhqa%a7|LRgTy=8Oq}z{*;$;}0)!>(ECj_(91ytjQ`aOf zB3zT^g$ghQO>!xu^+HOxP+O!)qU58`f;zoLlYGh+>(K&Zj`oL1Dsw>v?eJY|;AIj) zmk~Ng~hZYxE{HhhSqxI#`Y5LM2R>*CucKpI#FVdtK#!( zQ8Je%S<4omq6JLy{1%xcP1%T1 z(i3=@M9}qwP850MX%i)lTF4|l5eOlZtmfgKlZ3K<@0ujFUC<-q{EnP8#OXxIPdK7T z5+yU2xF)%E^JStWH==_k*%i`yGbQY}U8G5(Bm<^~Nu0=CK$HB)7H^{kOmYxY6`~|X zYY;}seZb2kg6<}CsK_H_xEhP53^Q4|+>SVtaQ<*j@&~$LqU3_v^>?B~oO{SwQk+hd zd`nPbE*bZUYm%NwbxEV-3`{|jtPW|tj}pGFmCVl8zncQ|^1q&twdZontP83lEH%Ub z&N1n&3#$H%ORWn=!=LtDFs^3!Cs~L@BVQ66wa#JYv}eli&f_{CF&xfQ>1j2+TD`-^ z?5eXE6XIVYo&W*~pn;sS-F+gz3NM}C&#_bcvgJwWg+-WJW*>@{HBHMOH*y)rgR^4# zSF(e%s2KJI7$RgiTSKx3Lo-vWmi$TM@;79o(A;te?qEDDfm(9QC+uM=ITjm^${xol z!|^J{c8KE*hoisCv4k9j$?>@1IPsCIN2BkgM`k?70}e-dmt!e8ij$+9;dsyE_!apB zM)_$&oF3OY97h&Aefg9eWyx{4I+v4+&=o)1E#uwFyt@u}K{x}tVQAlG>NRA$A;8Nh zf>tGTHlT3o%UH%?Xz#sKn!Ju_DwOSZV#nPb+6AGe8QR5LNxYL;#957;O~vVCyWhw`10zkX+OyT>s&Z$SweCo}h+L)pDDTm?``AT)-{kr}Byt9vh&qyJtRc$z zq3fnEFk}%^wHdWRFAaou=%t3Pu~xAQ-N|vM;aG(Znn9axIOZdoLL8MG4*uM?4E{Aa z9wo=6D(cWP9>+JBcA&?Z<8d6nqb>FL0u~a-H{^Jd9G`$I6BnZy?3(E=v9mJ0$r|EvG7TB-rOOd{xHLOY8*ayRR4d{?ltOmYsrc1?n@K7&hr z#~|Ck4KCRB@{GsxiCCwQHMdxu46?u+1cmjdkvLu7fbjLZu!&umLxwfCsng+l2=D*C z?^?325_b|yz6A@?l23#>`zA^I8`7{QvScZE$XDY>s=)`BkJLpASTc2uEIALe1S>y0 z*8x3bNkKm#^lFhuTJwl9nsUSKvSc-cqiabm*jjJ}?bvcWSruHr>0ak7%k`4xmAFzai6qdDgQFLFWG6S~?!rx|Dku3BXIfg$L3 zguV(W!t^;4!^@k=@>ipRbuEvZ+j-Nm`<1JMF??M!>FVSaDX@X84aMr%{x@@|6z-}U z!yS4Cd;2qcyNe9j#E@Y00rOp>pTuBFYV^GbFB<*BP-pp}s3Qw2va`un*bl*(eheR^ z8i&~8DYQTgH^cTDjJ{!=Yss>}%jkk0CbXr2rWxomt+wc&7*zJ5HlZb@M`Q^jFPc)I zk&HeV9SRuzLFX)x>&{u=^!N7WHVGPC3LGKp<_hecWAy$6#dp;;`oZqO-X36Y&yXQ1 zh6JNueAhL4Hz<{Ag zInk0!fR`l&%|Yny@`B!Opbfe5Qlw7^K_i4N0u;79$r&n|@SPTh9A2-)EdLbAfsnO3M zvS{?xq0U+){rZ+9n#kxw;7mW#3*>+r#n|E{w1CmO8cXh1(x%bt0WYHqTAa|HB9CNh zk3}bG-LTZs%B(4t74FImHoP5|+IuYvT6-aSs+HOGxWdZp27>V&cCOm8GDZ>A> zbt7f{Q;urk?-^E4R8Ypd@545}P9=!j3LI|6&v~~UmA7xIE^p^RuUv0u`~dy_g=jak zRcFsRqp-fP>o<1v(Q;1ul%kx6CCBl1eu5JGtyyJ;_DC?R?Bdks)jlb-_iZF9o?PLV z-gezy@p7}uC3u8x-xRV!Rg!Kfn@l0=FAUqut_@n+W4Z)YR2^KGY|nsAftO)@tgM#u z9XuAZ%D>~7U(ou5-j_@;;w{Ot|34hlE=$S6s`VXo)LV<+K+D}tS%=FgQa{8%HgDEi z$eeht1C~=z2-%Xz6$V*S>j1ukI|Z{Qo_`7bJi0w%8RT$iXE?J9xjKYwL*%iW)%Rvx za_g<)mn3~=2-%j%l?HjQhx`!ngy&vE$aX|dH^@19Jc3p_jyXPN-4#N%C-PB)jA9vL zq%W7AH-wNKh-_exl|9SihJ=F7miI z=Y)`*h+GXM`cV~3=2t%pf*sE_xX9~sAeJ5=awd@6iHdtj-~cveolU1#;6A0cUffFX zHl511$E7x%Hp8y=R`f!tZ6!x-G*XLT{GJUO+oj}P=OKY|6y1xW(~Od7U#L5FKiR?A zJ`$=AQU8=mR4`^Oe#09Xc{3j+ZcKJ|IZ~F2j~{f>QT_+aXHtGL&wc&l?NPW?UcQRT zTdwjsjPgAQj#@9HvE2vv-1L<gW}^pK@q6VVBZtrsp2iAU$IUj{P^MkBJQ| znVwM(Pn+k`GXa>|*es+3r$r#w4NT!{v>9vdM=&!V%guik_okiLz=8>nV5?)?SP)$Nf%2C#`& z0RXmT`I2TuRT|t3N*yx^>MqwHT+DbJbQ41P4gBj^@yyx$Pm#=-{7=EmDF2f`a{~Vp z$sB?Iq-WH=xWQ=+-G;Klz<1$iO1DRNHL6V3LAla1>gSHNtOP_|quefoxRqBxq>jl2 zp$_WEzc(@q6lIoboEyrbWs;|xXq*2--M7a_Rb26JAd3Nv88C96`p@d`+WJ3-qT5UGy8sRuG~SI?=Bw7$#^tx zNYzKI9fVq7{U+B8)4i;R1v8V60A9u`p#LQ3Yp2NoUII%H*d6qWtN$PxTCP4ucMQXE zox+$6B~3-s3oZ}>YLr+7>%WL~tzgx;$ukMmFS>yFW2o@$`Su}{a0rg;f#D*-kZvPE z%0qXN(e$(a4sl9sLr2;6MVM1yr|96nf46cErq?=;oBvO&j7EekG z=g|@x%M`m7?wc5a|7-?RQcl4KxD}^hIp~TzAOM+S0a6)r?jUf?U53W-c@%!~pp5k8 zVqewhO9u>x9s#&Wj6Y*75)-(i2{%%WA}u8VVNb%`1Y1`BK{Zt?NOxNEW7+&4r;rKG zZ%g=?f7uuj_`%<#3H)^CvbDgkL{&=QOSuJ=49JA25yX1CVATSjNT7iP{!=J)iq+?m z)gEG)Eg1R<{Mm0?0v`*eWE1#U2$}-_EN!f366Yr;XCXuc{?K>qRLmk30`*HwIM2PqV&38bH1R$#jm&FL8=t`r z+N6U_fw(f=4r?HtdUdNsj#|w?FpIbCm3ylwblQg=bKOF`yTcB4FdMBaF z@|zG-3CFsT%CS-N2yTU%LQ-?4Ma?ip&9?{~bB{&i_zKh|1=>n#zCrxg2sPNVJ|DqB za?@Dqzs35CQO~a~s<)^I%@iac0KTFC-9@0Wg2cJ~7xb0*iRr~y@}MSJyrwmRL3>St z;cjAh_c(e@zx@UVoAjElA(1~}?RL}x>mn@KknSX9uHYP84|thX0(w6|e*{n{-B7NR zvHW*W5F7L@D3E1?Q28gl$wqTt2%1xisBB*)?WJJ-8L`e1tlEUXpLGvMdrh@|`w-eV zgx?awP{Gh|5ncIpvX@@dL!5)jGZU$g7rz6&py_%%ZLE(G=c8_pHN$ktB6>B1nPTL% zq@tTGBGSUS2UAF^`EF|}UPg|kye0#;;x+x@K`75wP%mo!2=1WfXA67X-{Vv~mBJ^_ zB*iU#t!H1yqc2&=Ot%UCt0i~~#w!vNxaSD>;RqQ;`s#)EdPpNYNKI!aWG@ro9s0~E zI(Oq%=sccuo?+2BRMGhqfn)A+dVbeZ0_k*aWdE(`U(>lqOg8=T)6?kOOt=}@={%lp zT`a%g`=V*1G4X7g){aQiTI+uOfKAglviR@R=79Fmg(F+p)1QweN3^!xsP>uCmkF+c z5On-wpNvVbnqkWMRbu#_VCbi9!(*1Vt^8SbZCeS&p|<(b#{asEU*XIk#JvJMOD>d| zUv0$sS;J1DO!&8n?a(p8b#8!660YY@N6edWKL8R%K?L;g1bq>p+0?xMLYeu^UA1)f z`;E3gVGB&F)lRGwqE>PAZmAW1Y4>&9ie2r#AF8trLl^b`4ep@+PZK!iz5|Wpr-}OL zxO^2Q@G*%#L5PN3ee)I$RENh>|1TN;(G-RCL!v*gB+y=ER|V)0fnEU+Y*Yxns%Z3$ z9}g6b7UPYZWNJb%d`b-81cror;jMNdtR|7pRj3W27IrlkE+^#hXDO)tX98Y?AfQJO z)TctGjS3_G;-*pgis1swmdwxPxL{N8p%y78=JllH*Bx zC4HUAzW(5%&|q(I4jlYfcJ&&JS0pBIBMJ8%z@akJuD(eLrtE65Mdu8<1dh4;pfT}N`_nm!{U4vAGa``~HET=MPUmRCeRxz>I$z@?jpgry z%Lo;n0Cloy+KDmm!%YuhLSWiFnUUA-Ig5g4>x zy@_%@pBScPr}ejAv$XB>`?71>=};VM+ec~Rzd**1UBUi@xIg@%&93$jKpvQCr%)z* zC9(Yo*hJk;_pg8f0mujN{u1t*n>FJFbUHz=&DJra&Ww$tYyk+~N$u}FGx4wOY8m$L z#IAZ6H)^%=o0E>lt=QGZA3=3Gz)n%CD{u$3`X`hTYV{fXv-l>|CH>V~D1rGTy5~r8 z3wHHu>sYT%rqo|1<3~N6RlElPp(G8j04yTF8bRRPErF~|)qIQAKk-?T)^RW3R%i`D z`Qn?vEunP@?m+891dh3Pkk*rgR=pJ_U0ubl+^VZb@3q|Gf5JPURk9}&)yGzwF0zYL zQ1F-VdUp-i%7O2?VZfO4ufbu(gjmysyE1R`JD1&%Z{ILw3~t59#Tb}m+ttK#OA5~r zg{PH4mFb+Efv1yrps4&_lHjx1HtjHNIEU&Y8<&1ju>&QB91{R z9IF+M55XPK@o)x?eP~NMy1%OFxQ#g05y!K`xTaD5sY(6~*51b2dr@nc&VyK+wJti5 z6p&9HeFpYZzWP%~@AKCB)R6~ljlT`*M8?OE$uZ|PLd4w9!F@SqtS_L;ln`)Ish#QW&f!s_UC_`c(0>A=?X z9yYCG(~M6W;iX!`4DU4<+8fxZF=VF(^8YcWLTQ4F48QCXyGyKT)4K?v^eFb$%x8-)~*h6f8A=+n*h%--y zAZH$ue!5q$fdVsnmUG`vXG`!^FBZ!o<5F=u9TQ3g(fC_ot2XMWXx(P-e=~ z55dUKg1W5`tMI!Rsn7X>!bRnF3dQ*DCc61Rr#-DQw8dI_AF_h@T{B2nI4q!V z5cKRUJyRvf0lQ}5KFj)wxaGt2O;GN59!UH2Uc!ARc#>T4?j|4O?D`?6=t1jhuv0!| z@F)ZezZTF!q(Ht)$aM;`Dhas^qe{3Zr9t))a-o7eDGB+by9hZv4e~ugPEe2^-C*^8 z+V=?g){XYw-zVe|fK0e|pdz^{3uzy)@?8uE7HX=5g0d=aLNFmFbP3FN%7l))47XxJ z&-yORg}~pVGaG@w#;p*z4m^wBj!_GND{uz_ZzpifJ%OI{--LIX z!0(g5T(Gg1=Z#@NUW6De0>24Cq=d;|^6ljrjVuH@QUu1VMd%r(Uy_T^xL@H`2>jc3 zK*WdWR|tF+cOdZV1dh3DxCl+N6ZiuXSir8QC<0^OP7z4?rwBZTP{(H{FhCzqagh5g z!og{@VJQO7#jOxHjRelN2%Mw{JdVII_aD$Wejn-(^{Ox3|BwWp%&zYlBpkd0EVnpV zlSbgFgt`_`SvdGCM576u3x`$+T(3QcBe4UHFRA<%w?g1eKLQcI!a#+CA>4t3cPg*p zI5dvu*a^Is1QxUFPjf`w=cc-P0&1#f|MEFAdj1qy-Yl*<{V>Z3Z0MnlpT+u$XTQ3?z zrgcsCBZzZo%M$JbNHe4)UqWoBNRR1DDu(j>6C^hOthFHBbp8x}pS6a|zR+||UA+L^ zbf>!Z$O>}nNp`BmXk5U49(9n5`~veUvR|RDUyb_#&!8pEe#(}~J9aC}(ZI@LG$(-; zu$X>c!hMz+(2-9|M-}L(Z%*c-Lb9+901_M*ZXWThLCBGMy@P_c_9gZjiIL~6a5xlzf#pB%G9&Vy$1o3pif1rW<)m3!Gp9GPgMP;6*OIv1B$+mFZ2d9lE09io_)xF;hTrt!K-^Bl{0K;A z!k8u8+cA2-nLhkCEODJy$?Btw*tK~^BF8XiA2gyzt~V0hM)~ur{=tck z*!?8%(3_a<;WwKjW1y#oITumIw!|eR-o$J?#`o}Lw9ObTMpa>$tBMSc+j|vwEAmUx zf0_4EFBw~Fm@5l>=03l9O`+fX#4s-hrrv~`uSp~-Je4Lt?&|yyeOH#}tuBP#M(&_X z^5-z8XXuF1?%offGLaicIKqn}H+rUpFE!Tf37=-v&nV#L#&Ol=i+*z>K1GIzD*iZ5 z?e(ssItF9=5zs`{Fz@Oe61>GJB)r- zff1Wl*f+#y_V~;#Ms!{gj2e=|l|=>)U*TYB1%o);POijFi64K8tId}nJx{`&5BkYT z(|Ih$X6CIuv>BbOcE&D$v2RGvp+T{eefVA*suG5$Y=P&7VF~xg(6o&eMQFCkA6ryZ z>oXTZ_RH{@vyKv<`8Fq&O^Gx4t!9oFRtTL^RSffiH5}Kv_rt?+4jt2>_b%Myd$s5X ztXG`p2X4T4HyA(cTdZve3FC81yZf3&$zG)n;75D%X95&MGLK&Si5|-p9Lpyd%Owf- zxx|_r%UQUSvEaMhXC&NT=VZiOJsxN}ICW$0XRw7P=H=-QUi4G0%qh$9Vrn#VYJkHs zH8AzOd8PYtK)3}RV3PP{7G6e<#OcU zZh-(&^2ZJ2e}Y&Xb(fFcIB3HP!#(n-w-kDypfO82NyS~QBbaLE&e*%m+XGfPEw zQ$;Srcwd4smbRKfx+%55Z~n;_U6@xLomM#iQp@_5ly+CchWYTY8mmZjT0wPeRsqV* zVk5eW){s84*B?7~y)QO*GwcMYgj>{A1Ik^eRXCFN(PtjzGdKE8e^DEqh!e0(`pbs7 zx?U9wHF-v)I}cy~55Mb!WPIjd4y<_qHTYNH>Y4>)Y&3s~-QEuMm2Yu%5eiKTkT)#| zkMfy26Ykfc2IfKfulSt|S_dAJJ_|UccQ{=uV4Tt626VV3{FtwNe`x0IhB?GA^91G3 z`lI|RQSMeK<>$_c@@2p&lzT$g8j+1?y+8ao6teK^@OYLP7;B?3W~0$_aIi0W>M-YpljkGQgcZTU^wskl|Lkv-ELksM4$y z7Dzl)PD095(K|?*?F@UZJ-c3JCi538r_A@!;VSP5m%`mIf1Q>Wx?P=TxGLW?*HSH9 zPwhR`6}guTL5CM$ycc1-y$Dsrh1`n8bvF3mE33#0{T^ta1g`<~Zj3yD3s{G4dK;;G z=AWVDaF!q(oHwJDfj?iIaBm_TO{38${|FkL7=o$SNJUL|{=oxR7xHrs^1-$4Xu&u` zrejS>?;zYVka!z(9$2T9zQWZ-?IPW^ezPObd*G{9P3UZY`M*Oa8}cRq&S64gu(xh` zU*s{g@tGeW+HkF_7ST`3OHQQRkP|CMp9kX*yMnwf+Vs}XInBPV%in)h^k$&@e;pLU+p!YLY<6N#V zIDaOg$mc`L2q)rOMBClWB`c(S!=%Ro{{+4mTx(yRQJ()S2n!z#N=tV^&!9EMy-)ue z$jkF{ArdH;>3$j;?D6|u!X5l<;M4-FWx1iFQVoV3;@ogY?qST@ZK3(we&tf9Tzke7 z_~;k;dlV9ELWCOnll3iva|`Z4bTC@@@W_)p2xi{`s9W8Led-5}T#gW(jgfZRa%8 z2Q2%qI9&fjRsU11{vT;PeE+pz2zc#00dOG2#!OI{RpzC;1sZ9ZdQ2Eo4gm5=#-?X|$y=+!N-k_!AoR;mn+`M2#Gs4#0WUA+)hZ@v}zp z({y^5%DA9~=i@4Uc=#tLi}onvBv*;;v4tU@|v4D>fx3=MY}67y(71? zmKyE#;O;JcXHWKshM6O6L8_oDmI>GA)-G{e2gvuHQWmF^3t?9cYj-9*>Ntl-h~&t=4$<0Pt|*k&gO}XI%gB zBt@l7)iDE%Cv*|m{qF{lcU~I1Jy2{j{|+ip%>DbDHM=iNBM&0&8^nZ2^Z~^N7GI#r zNm91{PjXfCV7EO^sDklUcLCszIch-loy2Y0RiG ztqC;3i2g#Z(_5OBLb6`2GwLl#v0kpz>#uL4*K-lwf)exJWy?BOdkoV>YSNv(#6}~s zDX+YvbJbojxh>)Tw4Rzm?D z7C%9}t8KEPA@}(kJhob^_#Nh{*~}ph^RdGR!~f z$H%D0B7WQBPpQJDlD+Nm-_&CfyzTJ|>aj@O_L!b2kch}_kAJ8hi@a@*Z&r^**a%$} zf#I-WCZ(Ku8o*OawyCE+5fnpb_y*!p4rj^eW;iX#SrzH0_B_#f+G-nzB z0uu)&nKhx~fVZ7T{tkvhlA=8s_TId>!f*D#bNpl-Ax4%iwu{Tkw^;dFJ!!qjb?!#q z1>r`eSp#>bEzcYItIHdCH^M2Gw%dfyq4-a}_dQ~a(q z8H4vjZ5Yl|7!X*f=A18ZNRlbz)RdvUv*o*mf96^$4%EKLDfx**7v_d<^uzT>#tr9q z=)i|bg9>!YX{X`*UVuKylyfq@ZP0dq9qMB4Q8L~c6~ftX0tK?0<$gr!%)soxK;v9* ztVjvsurl9$$H4D^n+?c~@u4z*4}OVcC8jm~LnzNAOtW~~KY={z?B)KGZJ)%px&z*H z`ff&jR4wpnz74H}5&ec*00${O#l2X$MDjk3pKAYLp3cI1aLVs`Y~T6Kx4@J-(Bb12 z$CQUw@+w|weuD31kd4AwSJ$_|>&oa8lm@0!bXu`LT94%G!a~N)gC$VzsHHu{H6jk? zgre8Oor0@Lzn!Vh=&}l2;{y!S8vW6Z8stK0!~maTL}$U1+ZLVH3IA&ix&RE?D}P0M zWYNgIQX#7)-mep>%VrK_$f=C!UBgTmQ=uN&Z(5Wwe=$3Zm@{%cHND3l%l{ru5Mc1D zt`v>9GlJ)?%FWOS%a^|YQ+1lwQLGw+y+CpKXe`ZzZb6JqZbYHnD}Dk zh7s~yLr#gdUx~De7@iwyjc67BUx5Fy;BouV7W!pPtzb-(nKmfsugySiTY8Yy*RujX>s?wo2M(#H{SZ{|g|=0)Mn3&mT1k`Y(VKD?0ygGd@Q7)=;(Ij4r@DrO7z6 z8c98*AJ=uScKc$!LZj?xgv!`*iu54Q*1hV((ryeO>foA%rpJJgFrLA6I|JNy-O;^4 z(z(e&Rh91YBU1pYy^8R)hPjqqVd5j9f-!l`UDfOMtUdvG$U-JA{bhOB6HTmVUeZ_o z@~RI3(07hu_UP|(80H%G?JMsIjiB}T&|jYa0Mra%t~=KEImO;Q!7lvR{2APXj)$4+ zk+73)edU|OLll7qj3KYh-Qn=bjBK&2J(4UP&k0eIRw~~PM8|?W{89NZMe~jH< z?kr~i=$(*WA%Is(tYS~fw}yvFuM$ingvpCMK`Y>J#jro=u%&Xken93R+Nd-o5nII+ z)eV3=aFaAZx+ipvjfW+EeE*|#3&nLDslVMQD+o>1&+<2j;SeLx-`NtX4vDPqC!$EwU1}=jBCWdsO}&x%p*9|UI67`9|o9>vSkZg>vof) zNM6Hz>kbvuV0*Cc;k!AP({#CRe!^alJz@xNFQC!C`W94fEj`34rA>pGY0{ z#-rF-`4&AAUlhOai;(g<7@aF%bYS}`0T-Q$d(sk}3a2DXuIS5KAS~l^g)m=qyuts@ zQRJq({v0hVQo5hdX5!7JKUU@xUJI6}=Av522peqy*wzexMXj&0KKRXc>=d^bQkl)y znY+F11(|#sjq*ZQ*I#g*)T@ou-YFFev92PzJI*M7!}>DMG)r||F&_LmAS)l3h)nWA z!8SF|yqQyX-IkTjHs!8Gq;DC*G092ny6p@$f@)K*C)(#RoXQggA`w~6A$ojnM@@=kLuf{zT2+k#9v}()*NQOVx4o+a9dR}b^ec-xv z9^5{PHr7nm0Y0IyrFRA@l#00Oy5V^V@7w$XjFNG59M+!O5e9?p{>ESPF z!}zb;>FOE^kp0sV1S%GWabU{B2 z)^kpwfz=Ib`N0IvGeiz0ROE=%L8aMKY0jZ-^7h0B;XiL=?-BT~vK-N+69}Fvfq-LE zvEk_nQuJjUM&!&SM%82lO^UuJkC2N94|x*i+qdTdbN2;2_h z?c+mTj}Pi|R+>Z2L6zm3UF&`V+`h;sh=_iPt7_Ln>*MRDawrw9J2tAlZrDEBObHio zE^X9YY~OA4mG6c`*R2mP@s%GW?7EM_3-#7K&wqeZ8v&@C*swb}mF>s?6+iu4PK_}+ z>6;>^bp#>VaZ>2XC!z!*ZX12J^*OS#AQ3*wgtwz?`wU13@&A1E2SbM)2RK{@V60Ja zC9rFZY;DiIOb*Rd_{~FJb0;$AULN_0Ucx~gb`{=00J(ak3gB9XirW0Rn!NVY z1bDf^CCe?pde&HJ_V%6T{e3PTqY|}V^LaU`;F{i3>6+e)gAt9`!|+ENiaH_R;RXr4w54LPAseb~?j^Xuk8 zO0ztiYxe*Gdj>Qsp(WT|E`eF>>@ausygMlJ*CVJtM?-r;L;SH>C4Iy2*I-w(jPiL! zjp37UDw5yQb3OE;-}O+pZ}4_(3&$HP5ZoTmWfhcrByz+4J*L6g=+KhG@{}{3_=H`!1O8htTVq9eSw>YN3gn{1#Gbq|NvHpH60aQZ8al5os zz6SBDHNW?JJ!{mKCbpZxrzG6-poy4x;j9P2W`Hq!Rvu{#-u)zbX}AoShJA)>&OW33 zpEsU}SkQeNVnMFMVs(-Vh)GN4xxu_AD6FR_ELY`vWAG-~{ z2Z4_-N8UQZ7`!6`8=Q~n;EmQ_6_4A;{{@VId*T;WbZs&1o<{(C_ZZTPH{MdLoB%!*A20A6s8IW=5x?#Q3gZerlAiH^v}#Ihb=}r8ufv zFwrh9q_?@lTz_CUaz6=dfqeJCr{?<74L$MG*6pfvRdrXo9@;Q9b|jcZL?B`zWV{~w z?u+!~qD|h4M$CjqKKnE=)$F?EmBG0VWAOUKUi0FUdGN94ucsQrcNhoW=*#C5STT9B z(=gZ5xB0Gd0CQ@+Q7XcR1L#MOn4p_xX7>1SHD~0sT6xbYMM*8qqL9=IlHhYc3VYCbFHHFJF{|AVHW#k znAajHyx-OJ7=a?I3mvYmU*Hn>LIK*uD|n6vcrU>@DwvzoU?O4UC7n1OE=`&ZFmQy} z%r6z5AY*z3F0e#qF}Ml$V*gVTqd+xB z4qoNN5ViOcZ=oK!DCWQ6BOn*Yq#2gyuBr49Bc0^_`Qk1*|2R`ZlCr6=NVkdrXTr?) zVA7{7(HKTiZk%sGmhb>hG8{@k{dP<8*?d0jS>KIF^W*{|Z^gNoNEHV^O~Bsl$g}KC z;AEbX=y@BnXm{US(|!xgeO_7DZ-JJ>m+LE)yLq#Cw~rhjV#F3C`p%H#Z;(JptN}1B zw-)&{5%%HtA6X3seFZ7IVHhH}h0S9U?yK+|kFQ9$@4-`?*~kN#r?(Lx|L5qb+N^*y zpj1I0ypB>8vO}o+%+h+E%QNGBrvP?3slt0Nt+pl;(S*^RWGHcZM$(nC2ay!bh9$SZ ze?+c>|L@VIb-&$qZ`r=&d}ThbjbW6;63#sIgrH?@5U;76ZQ%47POkh!Mv3Xj+myEi z=l11<`yy2KO@N{K2Nu`xBHiSg!!;4U6BnJC12;s zk?~NbZ^$i_?)Dj?o$v$mN0PBI_hZXBItUT9y97*<;j+f7BUaj;Tl-NdbKx<}s|yfl za!dOC)zkdQR4^|0@w_C`!ALa&LPbxzff@4)i8NZugnP5xBaLdlX(TrKa6-~3|M#lr z(FQ)>Db#bO=n{jq-AeBA*kWT0;S9n~Ds6l;Ov+#>*fJ9OH`w!T=IHHdG z6uq*y#?4Sy*MnlC$XNH;&D_|K0~kEQ2PylmWb`7&2;B=O z+!um}33rRg43gdxssqVyF6G-Kpb1e^hX}j#0zBS*B}W32fyax~<1U z^Q9Qnenr({_1%Cis*IDE$+$I}KrF5&^`(&fMpkYf-h}ba^Uk-njH*f#)#h7X6My4S zp0ZU%ooeHfs{qypZ(fq?jKxsO_5YK_5d|4$i@u@*-x|N??>yiX#yR%; z3fKW&ha2IGJXMHmM`&2zjhm2B=CvI0eVoWa-<5`0!X3N$*s?^&)#CeM%lH7&P1-h` zEpArk&fK05j!)uzb2Y+DOz>?u!3eKJZ{S%96IoSM;|R|qDOX`j9B_C|W}7$hip}G* zT2r}jPSF|kqGu%f!lR6`)%vM zep(}ajwU9S`drO_p83%D}me(cnqk`4l4g^-V z5d1QUVrYDX^p5QzE!^p7$8Vm)lHuHydSlZN;lA)+9fwb59|trY{d$CrTHwPboe?dD zsmpLEB-O;XnF_U2;oS8V4*Za8WNEo^(%mK`rX9GM+fM}w0PxJ(=}|^19c8prV-*>kQ|x}6LLS8&n;6}$8xrmG*zpRK1p>R* z1$3Lp1+W1w%qhf2L(=6G{_QB?Z3A>7V^bX;8% z1bPt>?y-Is!kaoDof}?^ut4&suf_L^0=T-E^H(EK8}d#kBo#hg_p^$xVZH-4B)jAG z!jYT%Zbdvmz96c?yj~mM^cTEi_bdRp)cKJA53R{O$Tq8SUyYvCG56P{=8&-N9=X2O*fgycLwBHD zpi7u_4)0%7T(PzccF3HMuR|AQMq&6!#C-FiD7{g(G~GvIgAgLXK`9(KJz3;&5XX%s z0z}@5!jb=I{_oJbZz0eOC#9zQPgk(W`f~M;%934QLL=(-h*+jP2-G}*UNvRK1%T*h zFcYECM){P5sKd*3vtaXA{ADT?XoSE<(1p=Zot+TURqyWSQ%T8Q&s-Psz2H)R}aF$20@bE{dT@i z?5U)^=WdR?8IK+FMMaHxgNmBvHFs05CYvAQJz{VgAECkE3;9mt=6C?_x|;jIaUB2X z_8!>XHyB?6ptA>EZ04)V_yrr$K^zMSc@1;iUl2oa#hYZhxAD?^A^s`0JrUN;)>-)ntPaja%|#y^eB z`8@@7t;FlvF{g{ljo(iQP}AR-Oo@x1aGI!F4IF-^^BBNwa^~W11s-g2?!P*RM%@u@!+uqvoG3NN{T&Z0&5iU}Uy2t% zUHtX?%AdahFJNwjsLMi|^1@i=kHiPWPTs_m+OBns@@O#V3g2Kl9{_^#czArQu>vTJ z`afc`AUENjBEpoYdqH$u1VHAvmG}#~u47UEM_>7?tIsmbtw^Hh8iQZ5_7hzN-hD=5 zs}b|V+HKk51~IplMeip7#% z^PxhO(avVY7iBP@l*Qc3lQhp{dI6xBX}N*U*+F&**f5%l0`1$tNYn(3L@iS;HCPQQ z=1Ky~<2Nr~Kv(DTS{zwL=m+gTMv}d&1RBQ@H!RX^EKx zGnMt^pYtqkS<@qMp3JN05Om4h@Ky5CR>gS~4fg-v(7%3!PLRZL?km-;PWcC}`YwiD zh2O9hyU6Ck3NW&7T=En~Zm1GR)(dj*hMS3Fo~Xmo1Ls3Y1V7~!)V(78*gnWzD+hVU;&?lRb)jiLM$Y~XW&}=-Whm6q|q5! zXK1zsB%4r_f1i{A3_+Ip4u;jFGfa`bfZWf*&giKrxn`^f60d33|7a@QN(}#UMDRFI z3(qi$H>jaiSmOBpE>FT?iv3ps3s)g3xBgNJ`%|ArG1sn0oV9=qG5jZcF;(tHp(x!ylO;m;{#ZxjbH1+MNZ-} zOyoI}VYW-V)g#Oz4RcuuO+pDYVlu~u82b|7n2BEG#TTGYa~rwxB!`xiQi@+36QVL7 zEC7CDOe2|*t_KOXpGX}1ti6(-*n`i^=HA^_+zhA4cZvx;fA};$ z-hxGhxA@Y_(G@p8L=w4{g}}N#c%8^#zZl>2dj_ffc84r*%xmQBHuT*PKME_L^0vdv z6YhsG5~HkfLAVY)dz(BnkCwBJ#scKbYjK1c2Biijq!Bi~F{>HLwpEbLjL5e=Bu`80 zpOS(2pM~?)Nl*_A-7h=wO`kp7A~8S0o(MMT!idPX#_`2GkhdE%!nN+_;6ZE}2Eyfs zY09etS8hm3?*(NQ+$Vy?;zHU!$7JnD+&_-k_R;$S_WXq0LQy^+FNPJ115$S<;3na& zhXDIV>vu4QkYoKBjX5uN(p7noW2^9P{Hjt*J1bI(4YCoWTZAX4mRuy?uj0&F^R%D| z!C%b(1!=_hWO&GmI=u|{&}m@7+K3rky)mNIR|4pU6;R(J;=h9K_MHG_-Hu^|hn4P1 zxPJqCgpC7HN7Y8WP*@-J%2w|QvhnA>dn|j>&;IxcHH>|wle@ilID}z)ma-4YsR<)- zc@5uI&VPp}WA20V^ca4I`*hO?hWTX8cv-Au{LiAWb809nY|0v&X4IfR$UwbrcX1w5 zU)pk5ImmU`1j3Br;Pwp}?@7n2yEO~jg2vAkY$gK8%+j^J-RAW zogu7%R6|NvLFUktqbhIy87Di^RW(qMg!@_Qf;kY6HFWPCLdzXRYtWSI6`TMZpFabV z?;FAIi$T^NMLY6cqFr24;`Rdv8dX0U*S+srw_VWAsUe=)?9#?Qp$Jd>f!g>F`N9~i zc&+vaTJcc}36Zl!2l&7j)~wG!t>4mwb7a^lO-QX-)C6k8|D7g0-}@2lk2STV)ZZVX z^HD?7^#$F4hIxXL( z#VH7!J0&}?xVNRSsb~(!g^o&!Lx95_GwN=$11Gw zSOy*%#fgcF^Kb!~dF1A;VtE>WM5b@@z3MB_9NLhvBujrKktYQ$^ZK`b2>kRip-FUo zk+;DNwGv}k&jkBEKVSMY8*BY$XCsCYoesBedM*BMEQ=6V*vY(EDF}+6Af|aUohKZW z`5xQDltJM@_}`0QOpvU^<`lC173%kRX9M%ia4S;1A>bCZZ_mIarZ(F?{v>(G*0?eZh1TTuOJMA1iE5Km3ka@df?Ws{Ta% z2I}w0k<#DCRl2{r!}dq}py!{r6AD4G%|}>``I12NVmg0w2JnbS@c^%6CW~8v->Zij zA`4ZF#I9UopXnmh?nD?W4p;j1GWV>q}(H3p3GH1wJ5oA4pEP zrxG>9FotKwmaFbARo%S_09$v4bk}(@j>I8pel^UkL zq2Rz9xbd6gqiBh6bG*PFpW21ilOo~f&r<7~zzwhP6;rqOt|7Ov?nS#xOUidXsNt}RTI++10N zv!b{##_V>Trjh{u!97!5kBu0-=9BT^e4G)+M;_&vZr>5HsXHzlx&oj6?(yDSfP<#F zt6r4GPi>|y0ben=v!$Sy-w0Rs54N@pUy2A7^Ura3Ln>r@+c&;?2$m3Md=3iNW8Iht z#T($muTXuv06%~)? zM5g4Nhvu$z&!cLS^P@>>I>fsH1aZ%azcdt0KFP(O)A0yq=C4p`Oum;<#E&{s*5}dj zD-}4n?G`&4%l|R!CBhfQ3-f>p8W@@EQ1j_DRH4&C zoZowj4dgrL$p7b$2QqJBXTtgDIXUWGMV{@qd0SWrC7XrseLPA1j&H}`+acGK-L1Ig zkm(Gg{krZOwX>-WS7LM2xd;{Ug&3xA#uJ(H?ztd3e15zYBa08?_;bLC$jDuI?!YjH zql4026}P+;ABn5|yHDB^c{?Y54WN->x=#@?gGAhpoD=5a0*^mhQ5eNXLZU{Ve&x3U z#}4FRH;%lz%G|rh=QwWU-unj_L2POQ8{#XfFrT$O4iCfZEkW-HQ}F%f)6vsz&Ll>j zzrj;*&3ug~mhXkLo~rtey(%Bdr>Y`}obY)tn-kHDAK7~`{t;NtB;cJr@r~kQIY*%n z+Bdw{t6*^6*aL|tLe5BHaJVAb<9J(-%se{Z2N;d=Q0#$X{M67~2j`W%qVgP{apx6=dGeFTI|%m#o?-My$U)KXfobgMfl;olJ}6Jsct)u{f$88dmUVM>{Rg$irraFPg4A;}|NXm!%v_K45P@m_4(lNru7aJ4Cn&zi zbCY47^uAREJRbPfg{1tq2Z6K{Z>)DS8(oVC82hTM!C1?TNJG(NP=GfIWnb5ioHf{j ztu!3Uk`I6Qi;7F}QXZl)oO4C9#HL7M(5go$Jnm2FIp=|I^&WWX0XHV!1>{dpyzk9% z-yMUi@(tmT5eXKemuj3~IEG#0V4D%GD!@5d+?n0R1YR5JI#%sb_a(fq@}L>4>Ryjg zitEy<0;9CYc#`2i-+DC8#7$|cD>%G(&&v5IW&t(DFb?d%?GJbh$>WQx@O!CLSX8E* z4{PrT<1FzzkiYU$Xmz)Pt-r^-gU#QF3g~7m|5v#0{Tx;mE6yXhh6klf;ETTlQjADm zQT!k3Vi5Ww9@agCMqu>mLBq@)iCikrevJJ`2~4fa~fG zv(Yi}c6D<^ya^Y5@7dbNFT<1gCHSKsYWYIht+U(WRjV^poTI(*?J$Cv`^QB-%?TeZ zro%9ijmB3kmz>P;V*gNf%EZM+@H1JG#gs>&cRkw5SidGnu)`J0?}TmUfO>zAXYs8H zyEFc%fP%4loWIidy+6T)iZ@-4IZJ8rw>-@W=BnIqv-37p9B)D!T2M3 zfaS60iE8Y=Eh%&U@j1Ns(rMJ^=RN-^zt#FY?v24)*Ot{(L6rkf42J<(QsylT&-0I2 z?|S^=5k_Qvp)q);>v1n$t2uIwKX&9+BRZnUSH2U6NoF325A?PVL-;qi$6wyv4r92! zxbID5BC$YGQ$|FtD{|bxt6|W~At(olnig(QJi6ue_)B1I=`QePc-J2INndmSoJLSs zY4P!gc;dL_^-yltuJDoZ{b+#o^g|TZfT?3R35G+B8zLhgBs4au5WmegV!te^;O5!d z_voOQuWL(v)CdtpuDR`n(c~?dGCusuozxYq7-FxS_r%=TT=9?!~|fPk^fo@NrK&R<+M{2RMRX zCSa%h8DH(?{sWg#zazo=yqGaK{;aIy_Y~~_vy8RRk!Sdcj-*fIF=D6eS;E#+UO~aH zU*YI|cL*l%8Q5C+ZrJLxI`8fa|)PYc0SR zfw#Es!}kez^vc}jUAwO(6m0gc{kW+m=&Llhnfve=n%K0Qs^L3a_j%WTG$Ys&j^-9s z4c`eox#l6R*f?`>WO$(w$^Y;h;Md4~7bRTyxs%s$<5=TxOz9qy;|LW`sU0#1AI_Z8 z#^OZh!-qbDd*xYCWFWv$%dg@3aZksHO4B)I41RenvN@*`XXErx<{XtV zPY;nMZgJ0n~Xl7*y(?RozJ)D*IcXo1E|B z0($L;I^($V?%&`EO^$5#Y;x|zErgAVmvHq2pmtQAxx2D_cNqC8U@F>s;ofk5B>!R5 zRzy#^9|eVsgUGUHg!x(!NPdy2w7blC4g@J z&AYPqZ`ftqZhP#B@4}PYr4px#EO-T6icegtXUGy^iz>&&RDq450^m&S=8tf0%dBcM z=fgLvu8oI~fF!08%xPef7NuL(PKMyS@qrPu2hYLF|1bYd-vS$oe-*T)_%~0NExNo( zmp{<41a#7@88qq8(S3}+x7hpeQ&{!(D!HP z@?2fc)@7S6^K^NuE`Op+3(wils(voe<)yk@qRZ=a`AuEkugfQNxlxyI=yIPfhx|d| zJyn-ubvad+m*}!lmuqx+hc17j%O`ZXRhPSUxlfn5-Kw7vx-8b^g}S^{mkqiM>GCFB z-mS|AboqoXx9W1YEvEnh+jO~F zm$&Qk2fBP%m#^q@pDu?yr|=i*a=b35>he-uHt2GdF7MIh!@At4%fIS!zb=P8ukfFx z%ky+OQgPmV7VGi?UC!3!VqM;(%Wv!Q z=eq3H+&;Qo~Z5A5Np25 z7knI!zv%KgUH(p&KhWhGT{i1-fiAzI%VJ#~qf3V_-+M-lYlkj>smnWb*{RD0U0$lo zN?nfC<;lAI>}iGXFS^{W%cpdCk1lW0Ws5H7>9SInCAvIDm!ChS@WyrdiY|v}J?_@` zmfd`1O70r^Syp*_g}Q$@qqN|c>*v<}|EqFuy;JB|)1XQVFIRLig^@~C) z+kzeA>n*s9=WQ!>MW8*nw5cN$Y!5cb6ANyO)goTbqF- zTZ=$oX)qMHwywFUp)SSFmuf$JHoB~K z1JbpahzF)iRS!%TR4xluUj(0>n!}BQ{iJjW48z3f2X8%gV0s2SF{s1P5u}v=2Rfu( z=G^MQtZELnEDbfLCKq{n`2MrE;vj+p>aVJ5u3Nsip-$O{j<&jbYa(X!r%;WzpbtmS z^!C>4f-Q3g;7SJGX(_v9ZkuW z82ifPi}hIZcj5r`nza-A@wH~j!3N2E9r6ltmEsW%g^6S7oriX?fj1>tY7} ztnISdiZ5=LP9Yf8pa{uIZ)SDoc;?UdRZhraZZqMgH#G-q>Ozg#K&9ghx^3{;M%hnZ zN%-{9^@FQyYKK%?+gA=mOa>j9@coE6EWC{vvFy}(?cijzo7vIYqFpU?ad^0_JPZVa z*AR6E-nqg0_F!mwQ?R)K%@m06I}pHfg$9R(S0Ea`v96=h^3J}X9~&qc)*(c2wuh}{ zA$z}EQU`D-veK#G`^kg^4+w9Q3E={Prk1AA7mQ2wlLWL6BmmF4jf~X)2JANjFhHX^ z5dT$w3P9s+XzFNdu3I_qxGVq-4})3X+7NV9b+$p_gAJaM<0qWgG1jxRHH6EFB_-O! z8j#)r1eX=wa_O?HA%}&}BDurBr%CQGaA_hvESybrhlR6A;xKSY3D_Oj!@y_da0Yx$ z-OA;`me91i_J*nLbuFC49ogos4Nk>v08HvDRiYjk0xc5KiH3}t-P#hIhuCtIr&U%u zPg94d1sqd0odc9fp2!dkt&}H_*_uv?tWLdidSpuIzp9op)XB;5{U6&+`XAe!7Xb4Iileje@%;a>pULbeEe6e^M_KwS`ycz8P{Ix+20dD#T;CE8_GlrPb4^8eUhRz>;Z{w9|E zZ~aZosxOk(hQ3WGvHg?#va(4NCY(3%{PWMpXE4(10g6ZRZ^DF$lO~sym6e<~`P_-; zO*}XG+=fnHYWPVL%O*~kRC4ZlY;sw74f5l@1s0)cIukB%yS&U7Ejaiw$^sU8RI>d1jo_yY(h%ELolU0%Qg)I ze2c?P&7r1LFZC-!jjeDT!r1iS4nrVdK`2_&^~>Rq1QPJr95C&gX+Nwkgsq3g;ShYZ zk>g8CI!196Xa~|fnaJ>*`x=0pKgy!EA-IIQAkqkbJS!T(X9%ykxv6ETr_NI&1Z(Hn z;g~(&@AtF^JHpK&&x$6DB^>eu+uK{)AydGrY*Jtvnk$TTA$W>#S}gpyU*3w_U}s%@ zsClKsV!w*jibs1wb<2Vs2;C;*&vgx+w$={txV5FO*;CiPG|V6Y5nhLgl2H+6K7f#N+YiAjfEJqSvR(Wz3grk48Fc4ll8d~p)L0Ns{Y4*wd;HF2;=TVAu?O)F`PB9ih6G`k*J+Ss!d8M?K5yR!St)Sa)p@ zg6;@n{=k(|jI-KViZJpLPX~nE+<++oa2SAaJJiMlb|g_FSeRPZ5v;O$7%S*UUP4@& z-c;}P&2=3qW~2M?V)ZB!i=rgSF0K8rGvStw=BE0f^1m&5m$U~tg7zjp29v?y_TUn1 z7h>!U5G&LHgN1CCwosR-wWw-_mO)tJ7b;8vJyA;n6Uzdn6CHCKVO$zK)6{GbsVdo6 z^9a0Wpk#@9V0g~kP-D=uqP>+}A{ZG9v8@D|^{va>nmFx10=6PCQv-pdY~fLPU_HSo z(MzkNK;W8iUGtZN<;a$VTk0wOQ5~KJ>{xPUp>InSp!N;HX4vzjJwUfGUrRmN+X+D} ztu5n-OBfdjz@XG&4q}J1KkcC~XQss?HV6cktvFl@BDOaO1nOE4zAMw6t&5BXq&v{i zn%q|geXaE{wesBBR$lPXMZ*B0V2;1id&!KsY7WB7fIHF-OQP4`)3ef>X|k1t z54S9C4YxFSmItw>F^dS}JQqt!OEA~~7oa6MOcIHI+B{f13Lx#FnyP9?sI?Wds%53M z3}L2(Tj;8IY{vb%25rr;E~6i;j4)0icvZ6W$pR*eU9z#madm4G@-Eg23@gZvIB;3$ zlFPL+5}-v}ize)Tbb7d0!@MFrv((b7EOs?Zc8qy7PCL&McooSe;?Bte0OaFn$;8FO z4sg2#uiPaM=ay&WT+jn1)hRpA=neKebb(mI)N>G62P@Q$wH>OEu}T!v*lRr)#pYRzHOX4W9Uy)ZS6#h~WO1VAiwD);-_m(QIAra%C5N+K8&TyB zH;761G=%9rpnpIUK&u7(6sUd21tTrVFAcU30;{#O^`e)Y#s-0&vzk2mb@w0Z%Z% zWi0hPiN|`b%!WfRgzC<-qz+DF14(MD3)MGTApjjjPd!L%T`sF5`fFO^vARr0ZLOmm z;RVAy_=iRDf)v%BDIRUI#wSN2V9KTNcr8D;ir(l2Af%&1)i={oO12qq9Uv;sPRHnB zHWJghG60FwEY{gbOg{TBNKCfrPhvV9qlfWaOLH^)MQB#X_`1dQ1Ioi1tvKtRj8$Nj)NmB;5Ir!IOGd_+Cv9yV?8_qeY>B)N;E)r48IUsFU76((aADmdc(lbiHJcJuH zHszh8z3g9!g@n=0 zY{jD0wZZldD3k{_3JCPnhQUPc0T#2N6=s!dz;c=5I)b$|V)qVil$W9$=pe&1+W{7y z%gUCBpN;mgX*d;_T2l4qz1VSUJ0RR9sb5E^X|coFSSAgYoUuiLb3usdo2ELxaDyA| zTER0MZE|?0PIDk5fy6{ejvZPH2=|HX8_n4^w)AO->blNK+29dt1e`EyH4@5R8p257y&g4nzzM|wmVqBw zU9n8|Khd(huCr-*cscy6j$k!BN`~p&bLhXZmfGE-Oqn=pYFXm2$!~6`{ZiTLUXK3y zw@=@QS>Dv**Wz$ABUH$?F|l;9!!buz4+*YWQyq?jm#TBUR=Q&j-aTtWzsyft6ln@usnf|sx$Q904B$cH8oR@Y zZ4r0O0Dlng*&r}(ozk)Ro9);Fnm2K#%mY5HcVt~#0J$WLLr%$YS%)-aU>v)Z;ovp@ z$stW!&jTHFk@b|y+kjZ&0#9Qo)YfsqIp+jh#;<5v*3=ekXsR3E+P?H0-kqa`7O-s! zOMCR^lj)>J1wJJYY}D#Q92mfOz0qAfx|S<{1I|ALkuwZ7jP-;&f}UD{6sMpGgeiwi zp<^EK%iNmNUdgr8nn`p5aUKUtV2fSO#fwKd`t2v$^uWOg(Khd_167s+Vs3QU>!~71 zJ+rC5$cE<|vD)%~=ym|hbr4IPN`uxw{`TV=@V!Ilg63KBd^t`_tKig%A7KAd{lJJ| z+a38~AuFlo^*Z+lyCvg>9T59-Es~}{ZKoURVd()Q*xpiDil&G7I|84XELJbcp#P!T>lCZw2 z1ki-iv7QO%(Z88c1~3P=lwqTNE%O?2Fs>tH*^%a^k|u%9Ln`mW9p zgKoH)u#d3wsA}qfB~$YP(uZ}ljHTz%IvLZ6|H>$(q+#&qDU` zC0Sz$u>&eo2c2v~|4QF@z+d6EQtSG?1$jR~%_)342ztV|4md9t(~{d{1Nv0_i;&dY zvJzwOe{M`1EYRK|Iu73)n;qK!3E*%Pc1kS$1XX~u4!qHGS8cFxq?>X3IMFDZ*G0ZF zsq1jyLxc|Dffm+M$RNe{{uGzONZ9lw$;a`jMW>&RD&H*te-i&AO>LJCw1RTv^m1H{ z1A`LqYlqu97nJg|YJ?+}USV+1L@|ME?nw7Sgr@gHatm8l1bIabqf$#s~irp_~ zJJ@4&NSQbI7pSb7?wegz8K9#ySLzY7Ef>F=^@_io2fV{NI%D>nORA=M=T@ovfey;{ z_n)#JyRh^((;c7<6R{-yf^3cmNXX=aqRQd8YEj48#fuuwUNruqMGa#{%iW4Gqc5`R zDIEBHII}IowbaRuPvqA;fPYmoeuCIs+c@PQn}t79&$Rwx?!te^vWgI|xk0~V#5VJg zg}D^Q$7*Ncv5hY^&$93$5I}0nw*NU@R@9`5J0#oL;lVB*&T3(c4oO!@@Nwe{Cn;6P ziL5Wf$PR{-YP-_W5ne7CV~Z|prXlv=2Cdc)Xo)6xS}Ht|C-%9`2RiL3dIQ;Twwwr_<$#VFF0|%5qLLcDZq#%)%i7v%{sM_sBRq= z9|HrN|3l)WIoyH35nFN1Z~3Sh&FAvheD1?!gaf_?>2r0ka6 zBetz;#c;w2Cug_;J%FW#|K14I^wJJlMuL4%F_9P({esn&7b8J2R%JAs>fyAFt{p3AnKVV( z6f?Hg3LP1{q`E+$CK~_*sap)@VGmxX*l7ju*oLPzbD<|Lm5{MeG7KUvNiKoX+Ih8- z=N&)HhR1-Hjo{kaI%OJ3Qrc>lhWVqFo)tml>NOS&U74Nbt+GQ4%52z@-El5?m^zc> zGxtHbX|Id|Y7m*(2V=#FICI+=UOXOF=Nz?zV-?u0$7z9cCZ0d3bo6-XPf5&X&y{^h zs!#TrmzsAv(E>EGCTaz+;!By!mM8ipB20m|#h5mI=elIM3layhtL&>Qb2!)q(7AlV z+3;Yx450LY!+cEo307{H?GNMPv0CzS*=D$&kN>B=cL8(js_w;?W@K9)k8SxGjpI0S z;*bfkUBwxQ0#1=*C&b#Dhs`xmK8C;g|XC@vK=ElL`SDD>X@TW7DWk&d-Jx%cZ7zOR|@+q1UzS!eCN z*WdDk9+)a$yn6aLlk?ZB}|4xH+zM{tVa@H=ojkuY#f>F4kG$W-rF7bfU-ZVlAu zF>2h#F=;C!VXu1T+hZ`D^}q<`D-GExu= zuJ}BGg)_DDmI5|7mw@AFUUi!GyB%26^tm&AepFd_ZX$L5ZRIQ24qVWys&(whDNpkQ zXbb`KK63Pajf7Ya=58d`CbS01{om7fpteM7dx#n=|EgbC>v0(EwE^|?;CQO;I(wbo z8MJGC+E2FD@yWWQLZ$~-ZuxF9-GM%?Q_qw0`iNVPdh{yNFu$fDc9^d|;Zksa{{ib7 z>zqE+OzZS5c%q?NZ9ic>y3kWgJ7hxEIXvdrqmLgIJKyuxkMkCCv{XAzs6Pa;IN^`A zP;F*RtuLL=>4!X2wjjsnJSyo|=YQ|61&lg-z;SaV5_&=;v073_+vcbxUA)jjK_0lt7>`k zJ$xE#Pu-P=Ll5;0;Nq-KLy;%<;_0e}^Eb7F0_&hlP3KbQyX(6pr1vKu!Rdx0xL=74 ze;X#oBD(obA5gaJr5?Djgw>h2PLFVPe$L@ypJ4fdn<_`V{bZj$*s9wf_BZaXkALo0 z$3M7>^;I7KXxxJ2i_Yiqxax7M*~lBmr!a{3gI_d+U=8woQT2rJa&XbC=KUDBY39y)5RAa&yreK(yJpDSzd)4KhXo}2GRI7uf5LUMJHCyPHm zTA2uMoIjg;?(GpAXW<4*ecp!0(y(OlaXZUp{p(i}@Nd37gYU`ZI{#_h zRlls`J!E)u_Td$d^Rymo!NWC)!>8tw4r~9~1B7?XJ^hFI5A-$g>2-^po%>SfX)ze- zxHfn+;C>i&^B%U@AMRxXa;C%=QTX}{?$6^}m8=2dN+3?#DS@~ki`z8tAhsN2*Xecc z`1fM7kd;SZ48Zx?;$e+V#))}}J2uBSeSeS4r*>(>N=_l8ZXDdyTnPAJx8C~a=6CZf z`NWj`@#0i(afU12gmurluR$-iI=^oo#?@(H=84zr1st-#y$~8yKvR& zDApeDZE++rH8&)Ecs_RrgxVwE(0l&JQdd!3Pqs_-$@P%CS2?M)18+QUM}KJh2xR@8|O!I)eKbqWJCN-@EtYmD9U-F;A?q4R28T8_>9+WCXe;82DBJsZ4$uR1%nO71z2)JP#|Dn`Z?@BYu$Q#I|NZap zJ&5U1U|8nYH*jdn-d$Ed!G<>eMk`cR-`1`8!VPVTFM_rhzAdpmuEtaRvXjEtfBRwe zyYp!$h4{D9`3{yHM;rT!wB5*UDYVturi+d_X#b>=RCxW*0T$?o}{G9jCf%gC}-qGT7taZ`a zUX<=7w6<$8t=-{{b!>9c%4e5VmX?+j7R8*A)=-P@Mfh$6Qaij(TH&~YmQ)s%xGj&i z%~!P373V#)9v=}{J+Oh=doL$f_eOGddC9jP*XU8w(CudM*8g^FXrm1SD``XT3fj=U zoHlf|(}pM4mmHhgY16g z*xPCClkS+3xfC*8khugh7t@9vmy}uT=xn2oE)R9Qyt?8ptthq^+G0y1t`N^JhA}%l zZRF`)MxJiauBGJJv9_|hgubkHH`-UCeFb@*RP7y`7SqbEwY2hOS8PdSu_Y&7lLHx; zlLvFE$=TRW8+(`2#%|EAWwddJr?S4Zwz#^0KCEqM??!u9TjRFnEwuc}rG?G!TtV;b zT27b0;-s|~7Loh>Vrm~)LN4gQiM}Eq!1YX&EhB6L1QK}b+d8gahWT%%4##?G)Bq9d zAj4zd+)kS@#?2VxW{h$3jw>pcmpY1<71qT%u5N?=J812*?#hZ%d$FxBH}44V`{u>; zW{jr|bB5g_oBi$Nhre6_f9Zg~tb@O-5`T#eBYse{zcl>5#D0N4B#NNu{px=^JT2sT zc~x=q))ln%m8Epeg*Nn!IS;hcYRqX__X_yxN(#Jybpd7HS>>yZzgG}pU&6kGeF^&# z_9g5~wtYKZ*G89hT~3$1e6c>*pHvK8S&N|p+BSE!Q`h+o)N$@|at~}o3|)a3+Jtdk zMc(fby%Xhm8CU&p$5l(|s=vFu(owpsxUR4!wmP!P=LSeQR>B8+m%tA}cPxuJR<+Qo zXO~wtKfHn-M!cNpT16W!xM=^5Z z?Tu}ChOlnmOU0BG3%9q??H88P&%;NT!>^a`SXx;UTO4xiX`?+D*IO|5n>fz9m#SEA zh!I;H+~T5JAjgk*_hBF4TFha|chPFZ?CLJeamR{Edu&<65pYppz(sF{{2RM1UZ3{Q z8++xq9s}fAW9XGJSh%zbxa0;dtpqNupiNH-E_FB&KdT5a>)ZVLc6$9Qh>;7xv-8Vo z<-iKW;!4D#n<|42Y9De?ZdCLOJ_1i;JL}ipMh!d;S1Y*=Itwj6_|9GJbQfYjgxC)P zr!G6cn3lso7h&#+DF;1?;vJLN$F{~cth;qQ4yS{h2jM?6Z8URXC0+e;N2T7g6dtVx z9<2f%xoP8*by&5mg_b?Jq_{b{f}-aZ(;?XIdW`FGjB72&KWwz9YdOVc9rOW|r>!v| zp1?!kA@C4*2>UhipiT2M-Ht?vw>RBpYKM+5>W5=o#)9$JkB2d{eoT%HPTBx_uPLr7 zY)-dR8f)06ppOpNb2aR~Y+yO;y^=EDa?mpnQVt! zVTUCxv;_TF_P*6wX+dmn#`?VJ0{jgzy9&O!2)G)Fw$KYG?g{P(`oea?cEWbDZFl@i z8~w__T3YiZtKZ_{0@iq6OGvF}tFb<lb`y8Ww4n-{gv zBE%8B&`KGUC#-$}WOctCE1kd}HZw$fYwxs{?KxBj=oy_nqa9XICY-qBv#%sB~scMwh=wvwAUdE+;L=d{`d+u$77^ zWa*cEnEfAdbnQzK||2r2hOdex13)>Z-S4% z0X)n5EUflvn-*Gd9EHO9vz1>AET+abq^|Wm*4!~Jr<1NhQDcRzy6kNjV;zrU8IG^u z)64cRDQ&jaw>E2iVE?BjPP!Ro?X>cP`rj&NbW_{2$QhTk(vpL%v6cwp$Qnl*6_+~c zuTa9g@4Cgb?iJwYImXXrR{IOs*2~+N|H5+O-yN`dT>7&AW?8j;Fok;gjd@gCLmp+t z3v5;ML$=u(C+$Fa#p;W7WN$+Ubv!CokPBn%Yq74b?L!X9bH0_cc+A=IRbU3NGPT}G zUqsoL!`v=gOqT)sR$N#{i?H5v`|qNJc^kTD{LOK@v|)dTrAvHCWNnL;hb!G;4f8n3 ziM27$a^BWXZ$lrq1M7F4M;s!CmY?IeL7obpWhe#d&;Gk!j>CoHz8%h3YXrwHJRig^ z$FkKYVlZ~4lfI48`9(GM`rnR_i$dMdF>q0^Ddt!XdqY>qK}wv1C^;^w;Mo0+tDSUA z7som-Z>6PR+qd&cFY(Zu`;=IHp6+ zy`c|BNwGB%mdoRHyunHTfbwsU!&Gz@axBG1=MG{!`%Rzt&2nI77yNI>;?PoFYp){G za<0VroKY0tE=3(J_!MFY`{V0Y>$;wyb&fnO=HC_u@v$Ckv3gmI^}yrcKWjX^A9Sk! z_yy=(Z+TkAi#qdFzwD%+pb*+aSi>&|g#r0Y|Mo+%8*ke72(D8fINtlluI;!?jYl)~ z@`Y4&B_R1*O8?k_cFZ`b8gg3aANV)_jeHf`(dMq>`&YCj&=#m`oBEoQa%eOC-Oh6G z_uBVJlpbFD9*NS!Yu_VLdU)-7BuWpjeUC)x;lKL#NbYrnPSq}q^>kZz#ID8C#gFj4 z!+IgBYCPb?Yd-iPqMkbrKN7-~Fn*f^C0g|T7CpE?&yV;MO}Bk;XF{PYrS1h=}_jDc8>p>+2>gu8DZ#-rmz z-#{<8y2t}p6U8+IjE&#of^Kg+9>XJ(UlyLX@{6o))9+1sJ3nBJtNZ`NIuRxD{e!h> z@eMWIM1LiF^Nmlp;bhtt=o&(L_N$kR)$WJ7pKYMuo?@xwZp$isfgMA^=O#m^_Td#G zJ-hnvv~Ebkwd=z*dtm&01-j>LCr&1?=evU z{f>0yWwU&+6tEXx)mJA@l_C(kL8evGwa+;;s|c z%XSaZK3OjY7Owd+YDi&xK7u2j+O+y1VDD6Fi;=>BL;C zWr6;>7{Hb5LwvVEQ8a}v_$D)Y60)uMz;$J4vgXix_aM8+{_Na$t0(^H{yF(tK{Qg= z2dnxWeZ71yBz+OQ@UR{=huirzJ@n^RjL5xhc&RGU^{h+22h38z@7B*#CZC6#J8^Rm zznQBClfZ3icun5ZmZaP8_PJR9(SGeULztTd4&sbjf2V8h@FaXJQT&*P%i6RwdJkHy zw;~Ao1o=1L3e>}Fdrm%Nz5lt&+C%KHb6Bs_6I;H%HV-J~PJZ7Q((^jaaQs}2nFtQN zT|F*xik_Xbh72~1e%Ym=koW*SFWc|o`5aZ}Yym zv7?9oF`yv$-vH@6{=4~!N*R0hBIJ7bFyjcWUPFR_Eyj|QvEVj3>%Ns?z16~sN9RVg zA2&Je#!Jd@pA*q~aPjR>O07Rv)04v7yw&&Zc;=QL`(~H;F!*=lRVj*p)!du}J9%nv zuh~XPaezyK3%il_hVO$*;>%+DBmB1T%ldT_j|A&X&))t!A38W-tvIir>y6v^xd+-P z8hZzBOv9~Vk0_;GSDOdy4fP+VkAP3m4ozw_>S@=1<8fHf$FZc^-ZQ5yQRjQ>TJUl@ zni6f-fKS6c^~`Z1_V?i34EyI=>K6bgVwd%-Nw{u1ZrkePr(X6SK7#v(;&WT@vb~7iG*s8dQKCI#J)}0Scr}NoA+`eF4a6Zq&w!Q~bnH=bQmvIenVJ?;>FUbk4Y z{2z6FsXan-bFeJNkO^$+v#{nc-!^!N-cws!#mDN_*1oy@_xA6_y?y-BM%skdn%?oU zEuz<{IRJ(0UaCV|=J@o}*?1cP;*Rgys#}t>+E&(}(|S%a9If@oc$@;27BuYYeVB*S zs~m_Pm>a9?iDzBr+IapFvcq+HVokga>+`M?y?gj}h6=_aQFZtT5-ENFA~Gihk)YPV z8!<{{XO^JG2pOCUk#}z17UsXNu0IV}2QQ8QtF!*OzAVJB?&G6vqF+{!LWUQ3oXCUV ztdi6Tsk36!^9Z0OyK3g#kwF-tT?@HB;fd#SGKPPhEuEgT3n?mxv{K_^#^5wd% z?yVJlXycGje)pV(w>%7iTio3gIt7$K4uKbNJgDx+zE0%ac?wUF99P0m)sN|R+Wq*%Z)Ydv{8Rty*Y@L1Qya9ewHy1&-L zH}7ZxEbQjA{lq{>z2TY8E$TkphlkE_bfudx&%OQf<7D6MhY#>r`4EtAhmJYl`4FBE z3}KCC2m<=-#(NsM^BXUgzPFcds%uqgI~u926(dnj-;JAyclGn_s9d8i#~zh=Ddv4g z5BA}OsBG?j`a~-O1i#?<{fF=5r7g&BcgbM1dk!Cb=zhHBP>=F$x9z{ojldUchO>9!rKv#_w&=MckkYR z*B#w^-+tQ-T|OoAjbyzH2opa}H_g?14&#Uy_a;aA>1%B4VWWHSRzK^pEa(xBW#EaV zNBC~{hw%mwwWper-gNlH!$DOVBh%;lF89`0$_upa#} zAF_{&w4Eug4h*xpu(U3;6mAS$B3?73-(I?qIdxU-)5Xg4=Ml(E9TVbqf8z zCAFs+UhO-W_{A)E$HD!0%x)lhytcdUx7L6I7we@T{9zfqwat2KC%@y#d+XjitOqTQ zA9w(7l|gu(=gn9O_m1mo zW5OV{K5<`#rAMW6BJYFhx1NWlsShZ9<0_u@_n1&EM}AU9__SR@Holx}FWLAIIM$zC zo;1%(;*YBFc{eMHE9TZ;LfXUcSM8bW6xIEdWcxlDPi~9auKg%1?eh&FD*l)#w_5tt z^5@%6Z;w8t`VDPUG$yoc>pw1h^j+0YN%-i4YCkQ{E5AeA8{2(0KFvQLt@#c+=WQqW z_0D)i9#6DCg10jA*AO_%d&Fx!H8l5V5Hl;u0U5XNAJn*0Lhb#AUL{{x_=+OOEqb@h z(|VncPwQ3NFJ+LIwCUg8pZ=W|KCjp*B2;hJH2W&~@_N1oIa=P#tK^#%zS2DM%CC~I zDtz=kWnVoWJ9SB%%*W@^eE+EAB@A*qUnQSk_=+MgB-B2>pzvj0RQ-B|+WB7XZ(i5< z&x8l*M^t>~Yyva?d}%#u_E_cB@fBZsb$lfEC}{b(-^;=?+#hC9-QKAyHd=gE%_mS) zwDK2?_@miFwsHIPhW{k$4y$pwS30bD;f}I~zvu(%`|gE)p~n>U%5Tj)bB~f!`lOPh z*B!k*dq8c^y|4Lp&6jyl$?xn_RJR92eq=Q@9jE52jn}q+LiYFhn$L6QJ~h6=A1L|u z@$30fPxI}%f0KW^jw$&b%_ubDX`W};*#6^x+WfoF_EQ>%%&c_T!t|dxqVyh{XtaAt z;!^utDc0z3uJ@|_Qr~IrZ`vP1<>vmZxBF(A`-_gdRA;07oDC;T{xoyExj&V>3!}$* z9q?z&pCSvShvY$}_rOP*+kHat)OT~EUA6vVf`g%VH{W05mq&0`@2Bz0`_4u`*4s7J z``i85E%+C3H}^*^Kh*l_{H?0qPyPjXcmT%a%+sCK3o8l#Eh!@`i`H3Enks9zluxera);JE?kXySj{c681 z-lzP+o)2rk3?&VIbHDN{_g9*4*Li{a<>uRU|CL*s$5l!4?%4Yj{w7W|;;_k|az~rv zZ>)V`^f;gW?8jF>?fkQ{Y+>}EakThH&HX7JSN03PU(viA|3qwd)%wgzo*H;a_LKdi zvL44}yIHYQm3VRIW(>V4j<=f?!ZfY)9>&^Z3OY1H0Yt6Uoezg8f z_SgBM>r^A&YX6Hl6u#K=-A*~*kSVMF?b~(#COq>R@GN)5Yk0=G^DU4bOzW|I9oBK9 z?dW~C!Yl8uH}|(%ocv;Qe=h1g^KYAP_sDs#$QK&7r{uhs9*4=Ff^vNxF~2{n$|Z>bdIcq}0}WZ$lT>wKm7a3c$8XB_P4+GuuIFVoz82rCd+!42 z;s5pgSHNJeSjTJjVtZ8<=sL71eyWCi#=Yie%N{?i^V_M_3!?|UuB5JSzOHE8_ZFJ3 zk0w0MzelZizUP}C&#;g2pUEG5hU*>P1v<~KMstb(w&RVT_W9||0>wq`IP(Y1{XuW9 z{7ZAYn(Ub}#COiUFn)arOR7xFQqG5)`1Cx2GT%a4$=lc{jr2T7&O4_cSA6#KCYrA(@-mMpzIKDW zr1+Iz_*NVEVtRZ}D0!y&hUGfl%%>EeNnTaXgPZuYUJ4Q)sn1`!U$69=`ShjdTR5uX z$R}}W_h+rYq>RtRr^n})@x{ge*4y-_`8ov;^5V~1Y<#-ku=ro+C)7NyHt>bS9+BTr zd~O3@R{AyZ>G2h`zsUI3+2m=yvfxJKbC(`pK(5PH#GkLS$3*}aF1Q7+t~Kz@%6zl3u3mJXx?Z>R{o7(+yk@`gPx!*~@acI} z#csvVD!*FWC=IKdT3KfWuhJ54rZ`H-eGxv9x7j97>%}Mjmlb?A;YLK{nfUbhl44)a zlWHDzKhS&unQuY-)Z|w&={GERZ<=pX*58ESxG8?C;-_9&7fgPT6h9~l{@LS5>n|eq zHSy{Bx^!M5akR-`54YfM=dUXLnfxj*cxB?#{U&7HN=W`^@~foebrG?fNzZBF^UFL; zepS|ZCHRU1FO|4-92F%G3rd`u<{OfJqk=D{`KHAWyoPl~ z`%7Hx8xy=Y**7YF@BVc)4^#eJ(6}aeU|-*Kzafe9g4o04&v}WDg2bE4;HP=fUq$fL z)NeuL<>a`+)NfI6&0|=%^gNk>->B%>_1}~|^mDN_ zcENiRJ)8KnpC&|JQ1oK*E3d@4U;NKo>rg7XU*W3?-d|?m^UJ#Ww5+SGHa%NIEE_?;SHPi8QUi56@)APtkzLpYsrgd;e{5dD+#Z+Oz8=xb9`RF? zo`VvWo(3e2UiqNXbBhhfb-$hB2PNs(lplm;z9v2`FE4y9@jp|1M8!`{d|F;n z<`I^4+8!S|E=l6Z#HZ!?q~ElxN2WZsB=a!wX?ba}?~LfrG`^_BuZd5~3yL3<1t(48 z%ZneF__Vx|tZ#Y2QGL2W&lDdykr#Pf zjnCv)Ug4V&{4?c49`Vz(*w?;(=;^y;zLkXP*PbV8zKR~7#F2e`n$ItMz4PE?R`T(( zoPRdy**y=R_JgS4K}`J5ls`vhzO#n;YX5Udo|Btree(*QRwW;@>siaIiXWuJ|Ll6! zd;!6YqTszL-og^UIq?I#J+!>IK0hh>ONaJ%P35>OBXQX&{%jiGjO0xwK5Y-T;O>m% zr`PEIG?jj5_4O#pvrWe{dBKBhLiy$-!e^RqMf4Jvb>=E9M^k;gD)vo& zNcFo_Z`V}#X2h=&zjkT9jP!eKp8U!ue&83qm~hP_dNJ{7dt`(!DtKVRA+N-niBHR` zik@f1uT1e9m-WrWr{#G?UP9Id(|q&de<@inO>rI&y9FgKP5zvdII7NbeB_tB)5NFe zk(YS{1lO+Aexj-POQ)>U74a)m9-9_iOMX)Ml_@{1ieHt)zMFJ^n(FuveD=ukhp}H7 z->m4xo|kC656Sp~^W@K+vL02XUsL=>#J*)Y-)S1(jNobK7nEL1{v4BjO?=vJE{V7J zJjW?z;q!@K8OJAn?-sl_+08BEOG!Ry(o0$98xeW-`D%NVq+gHd&y@d_wI3Mxv|a+j z7n6QX;|mFH%!vP)j^8@PzE!~uQ(Wf7pL6rXc~RCGxA>o_-<;rcO7a6!ziAm?QuJb4 zkGvXpC4No)1|>eeE`0XmJiSimMbA-*57YQO;(sy00~4QDaII6$x0~=eC3-ROX+Oxx zd;`C!;>{#4D0zfm^lbN2J>RnEIV|yO!uyKoFC}?|{dii-Bf)1ApPomj##8YZ(|N8L z!SRyl&xEHg@js8`iKh5S3SUC(yHDe?rV_vj!QJ3IxZx9jnSJuo_!pLS(8QFDQPRd*agaNN~u+r{z^d-qW(awP-tND(huY z=4;~9@_f?ogyb)+T8>c77Z5#%1P@GppAvaa18!(}UXhoVJa)0IUmYJgnMYalx5&Vk z*LjW{SGWv(Dd{&XIAoF+mi6tN>G!wAZo0kZh7y-K!EqCx-Y+9@{+Q_H;41P@I3 zl97IWq8Gb;HEx7tJr9c?nAZJSv4@FI`%6sxWkUSL*stU{Bzc6X-;DUxPFc?{wwtnC zLG1CE=-Cu+5z&it9{YMEj$(40XZL$OU!TYeOCI}1n;&Su%89(N;IoM@DLAxto_Ul+ zURv@slmBHUk7yShx9dgEgTxOC^W;qhS)?#Uo9TReQ2fBer{!e@ zUxISHdZjHc^?coe8$bD&TKAV2_!1JACO+M7RmMkx&qjZd_%QKld2v}65^_Af!7#qE zjBlU#vuPe-(X)w9_gfYH1wN|uVmi;75x?3qkNzUEPMi32zj2v|KcV_H<$nbkpG)*? z@)r_4=Ok}8$qR~}z4Q2=e!o{h`ZeLMNAyw@JT>8DQRgLc9A&~upNuau55B}T9?Y{Y zctze88J`LNQW|$9A2<1PNaVSa%5EmTWCj0x5|^g)8!0VMaNLBac{z?sh&=oHrsKRK z=hsSNHOJ&Qd|e0hDGEbFg{&o6vW$vo_N zlh%tz;;mic_u~9n%_JuI-$q$~?f#5rJ4K#f^kT}#XJma#%DQF3-Gca)Q~I^f zL;FEW{Pcq0kSTuSVvolJH|%=WdT|Nv`X#?N#Zg-PrTmdguWx>d-}}UFCfuzGo|^dd ze9OY;5xh6qtt5I0%K2;){)I)}6XJh%J!`$B#1DLu51I5*7X5|95A5U9^Kgrw-Z!6p z#cs)Y<}oYsw#qzAeo&QpWW~Ow^)ey&91>hJ@#*KS-E!W-j(=KzC5dwrpVmu7^!K!! zFR|mFmRFH^ki@S&j%v6oc>lD-hu!aWzY+15E`uLvzL1RXQNb6}_#zS?Pe{II?^n+w zEb<~UK9inBS{@niM^o;>|7cwg{e@@~e{YofEt==`Sb#;+Eq}d;DtsWkfHpNc@`S z8xX%DIbJZ0FD3RM(X(m38PRjqkZ%^n0Jn z^XQKR*Fxe4CcmE%yP5cOzh%+$^WuMYztVg@!Abu-cse8aGA!e>uM1k9U-Xg?`Vd;`b4eXX2X`y_op)_~MdBq~=*Klj8S9i8qry64I}UPxtE*c`3n{)nxnA z*EPg$DY2W$PvgSp6?rB;mp-p2^EKgLL~!!!f(Q1zM9-rj_B|)-ktu#7g5%YB@&ljF zUj(mA_Kk|4x};x|J$#~5ilRaXBR~0$# zF`cjT37*bM9${LKGGdR&JjYR;Vvl38UYhW^Q^sfF(|*t?ejk-}+7#z$@%v%%Q`0(= z53{{@wgoBT8={!)>3#-!(@*dzD&rStn)Z8yPFlV7_6g5z)(5(Vq#&OM=gji9g%@RO=-u{YFHd2@hgo-?;dT$-XY}mzemUDIY3|ytIt( zV*FEhSP;B&3I3VRGq^<0pBDWY{aO6aDSUSQ>G&;)o?rQxvaeB|#QBW)l}UdEkr$JG zP5Mg-?&bxbP3I%B;->}itBdugGW=Qb`(sHp4^zC6$P50m;SJLoxbMdQ3#cn2f zA;IUOoaYMKmpA!c68pwvo!MjH^GLr*!Ew{^YDWC3OYCNf^O%h9(~{Sj_$qo`kbH8T zZG75aih3RrN2c+`#SeDQ<5wveU-g5^9wxuf$$Z^{Lq>d&enY}%S_ea-=al%fX&zDW zm!Hhz2N981l=F$E^KfqAt9(Mu*Tk0+J^RF;P4*~=-LkSSnD`>X_o%E}c7N75nUy$C zi2h9Hxk%RE)DvnRCckn?Tz*>opvB-G2h19&W*16Taj`&wg3oOt|LO z{R-YYZR6AZdWEkyq2_BJpN@~PUZ(}uOydj4_&Vp|%ZeX_4CjG$zq4YuZoysqJTzZM z)`j1jCyz~wo;~7MCjFJg4<_b`kFXqHhGl#v9QVummKVF(<6PS#DfTExo@iW;Bz{8@ zZzg={6uadGhfHyq7P|%J)1SyfEnzqYTe(Pq(cg=LS0>yDNPG;4o=xM+$voQU z!GnnOTNGR~*)1%%R+V+tq`#QNWkC8h@g*dVT(TZ*u;GxlTUhMtk#*X{m(}^H*v)iY zQIhfXN?u~pUsdc|5x;tqZG1X!3d%Y?D{*e}0}{Ix1Yb;iF0q?y9-PdHJu)KCjvHEk zX^|I|b;g7TC4JmI&+)lU4aT2ZKX!)jakZX!Y#R!jezx9EYa8Bw+RwlO>EYPBmELKv z`TJ>2_9{Nu++Lvt`fl{RiZ;AYc;5XMh@rSZ-_h0gC2G9V!`JT#FI}VTcv0L7qsgAR zW6kZEy8N~HW7WAANDn4^dXFl5#1<+2+w<(`d(`&OH=4(-|30<7@}=h6wcqIe_5B^X zJ#eqczpMHF+TXnK=I^K0a!m5|{=UGa_c!@#_yILO`+AXC`I^77?!6172YtRp=l|Ny z+Ma=zn&Xe&o>}_;X77N+gWcY~w%6>={|0 z@BV5(HPWB4{Gqf!er>{I{at$Bu* zxGo%P9@iSLLpL_Z>)Q7I=6J8aQ$jB`_b1(ds;~KW?T?uUns1+#{3LUv`S`WnP5xLg z(y@u!l>NqB&(QAo* zf_e@#)k)+zcu-5PdbGf$1B@iJnJ0)Ayn{&%%E|ubWh3@PQ(qvc|x4T~3X` z3;K6oQe(hz8~x~MvE6SG&HQ&Y27E_|p7{ech9c+`aAzF)mnQlkf ziMkK;M_*NAps!(EUsrm@H@IotpUW6Pf8iTy3^=x=d;dc858C;>8Uwy5MmN8p+5@0r zlzouTwD9*t-KaDDAxZ*urXT(ebcA{e^vN=O4D}r7s_&`sdqLlc@;us^u6YUHz(bws zP83fT_61$~FKYa5P<#W+(jn6y{Xlf}uSD-?bx)v}2XSvbz`b29yxmnSTEo2Zd2*dd=$`^cd<)??HJAb*4#_9O^01 z!<`N)pdJJL`1KAe9`TJg`ph;po(yQG&p{>d_(1pEsM@jKQpX$A*u0?UZ&G8!chu=C zH#;n>D1a`y#X(i&q1r-=^*#0lf0lm+OPQOP6r+6cFP67Me6Qj!f$l%3^dAAeu2+rI2TDiOIGHYrDt|zZ~!>~J#t))6Sz;` zKcV>XZ7h1`q=Sy3-y-PP`xJi;^pkz69r*=)WE*H*o1!pHgE>f!_HA2R+I<2mPl(2Ynj# z3TXQf{1A1f#c>Dy9_t76`zRMsXZi~h=nHkGQ55$W>s55Q( zTL%rG?gstMZz;WHK%YU$pq=UUWd}{5&h%|4=TQ%Vc6?9G#S8kc|EO$)9G9N^ClxOx zQ1{E=$J)X4xqngoCD7mgf%q8cXMZU12#RkCTl`G_^52zxOQ2Cli`5E30k9mm=9Efj9A zfF5mE?J>}oP`I6zx6mmR&V}%uY;vqn?fAAgJ&wZd_})3KTB+J`&WS#Y!tFQ@N1NTM z9pBcYQ50^+_XdHdsvY0@qf;m}0r{XmLSY`{;PfFB9s|C+NlVwLc6^JJehr1&@%=^W zSgYFcO-dR>;r1Npb?a2S5A=&D++F~^dA({6fc_y0x8poL?Y&I3Zfa1@9zC9{(Kwm&{gNNxW546xm)S0e%u!VM_ z?gh<1*Gl)X9MD_;y4BK22=qA=URz6`pa1_`6`q4G`I}Z60KXgb2Pm9l(+jPXL3sl0 zO#c`EMxE)}zip+bQTKxW7=>k0sg<5VIfr(p-$E&(&UE9qTImAwg9g6cN>$XEPN1;8 za-b!Y_DPHlbj5{M@}kakCrTIUOo#uzmG+>{^eZUbUI5+t9h{MeOdsgBe`uvJ+I^r& z6xMkP^nao-PZ4xkS+%=C--p8ODbSas?)`2nb))dU5zw!pFpu|pt<;ag?FrByqHsI? zV=KJ_h1)}*e}ZE51$yO+s@)6vX%ueHfPPcjOQ3K4XXqSbX8JLdIOQ`D--UT|0 zavu9KokS_2&h#aeS5RlV_y?`znsQq7YScZb`#?X>b&k6q!saN}+(ExqZKY1|Fntzf z59&<+1|@=e3G|o#t(9V^CqRdOqI@z3`nmt5{3-)_9))F=KtD`QdJOz2(04iDNASG} z=$Bhmy#RUvg>}XB=UXu+@H5S!N6Dhj^y4Ub)R_*V%%GkF-MGwY*~km}EQ%lYDuD)< zt9l6ZH&!@l7W|==PTI4|X&onqKwn<1+G&lGcA&fh9;UyKLODfS*J6&SGhHurrdy@X z^c^Uj;0b|#Xg&HxJq7wjlzpf({autW>P$TzP!!!JcW7;^jj!7)GMIQ z4$K{Orpr(Ys58BHqm#~~&a@xpC#W<1Rh0HGVho@!ZGw(arz@Rw42AtU2KsH3PP8+9 z(Cefw)S3PUN)Yu7=w+J~j~Dd&S7H2UuYlfhHDsaA^jVZgQD^!xN(yz_0vn;QuNFX; zUZdnN-G`C^57VyKIq7NC1E8NkIfpva&s~doq0aPE*TG(>XFy-~dg$Owh)vM{iNY~b z1pVXd)x3(JU0YSZ0nocq+~8;0x(z(2GyOS~ov1T?8%hZE80a@ptat?7wO!RipkGB{ zy%j;1`ye0uZqR2@EPl|kP~^wPp*1pPY74C+k( z{SC0!m%;Z&C*6X=a}0nEps+rf-hLDG2c974S5Uf9|2@#CA3Uft{bdv$TORZ;q<$WB z`OT``4Z26_Oz)NYeV~s?o#|(#{uJm>PXO!I%j%b>a(Day#=@jo)ecC+pYFx5SSh^FDmIum9-D6SrJ@!*<`b-oqyjo$Nh&;{IE%y{r57 zZT@S${R0P1^d2~N^2Fg=u03_Q|Jt|w{PMP)2m1RDA3u2PlotX{^xtyrLwzUS)PE>? z`1pbTZO4xu>O0wg^2orpLnn{F=|KPS?GN8@t@rqW6Gx96?jN|jzBd;2b6OUDG#TT6 z>822T8w&7^_(uXG!I98NWF$XQ7@-7k8||KI4bBc$2WcoY6dsBW#fIWT$)VIxdMGsp0f+W;j1w7%mN$hbzObGww5< zGrlwaGvPClGl?_FGubn_GsQErXR2pt#5>YC;_M-n6Hk<3VT#C6ttHh4C6 zHhVUAcJ^%PZ22r@6WL@olg(yx*?e{;Tg;ZTm8^TzGuk=o8x4(yN28;$(d1}qG&`Cb zEsxSza?CXz8IO*~#}nhp@$`6RJU?C-pB*oaSI23>J>j1SP0UV&Cv%he$>QYfWM#5C z>7MdTbx!%FLQ~4qkK z!+vNoI-G#cl4nY1%FvH%#69AHhP0K#uyYhzN?KaV!{Vip@}Ux(s*F~lC-<0V%s1vA3yp=xVqlUj!Z|VW7BcgYX$2Yh%3{X31nt6K}&D5 zgO$PfP<1GDI(#|?pJS~leR<$_0eD>m`ieti>~n?Tnc-P@9i4HV@t)~C6F3uu$3-ol z%fsWsBeNquOGnYOiL)+vQx*P`9?gt;ta+!#($>6r)-KF7JKi~wm`F}!CbIC8%0zrJ zftj#p#HQkwXJj#p;?(R^$?^}^bmz2hIy4=|j1tqC>Fo5(baA>eUFG@FBFeyTJQ*+M z7liM`GO0|u<~goGw-uf2HHpC_d?q(ol&JI$bq)m)n;e(vp$zaYizVZB7p#LlG7q|fBf6f93;Kl8!M*uU7j zvLm^XBJ`y_D|j}9XpEmtpUs>toSi{DR?fP!o~%C`$VReJ=rU!+!Pi{17>-XRrZQ96sTtU*GF6@OOnavT z(?QGcQq$?_{B&WuG+mx1_aYj$;@X|@W&D{i;yVG<%w}?#VrJHgY%dTrI2am?A+FQ# z&jO;l3=ee=d4~K$fuRVnGYQ7%=>l5%E`gPd^o)~?l7*2O#C~POeb!@nb>wXHY!cC*JDayKld`UCXV#YuWy9Gx z(37!q2Dn*)-+M;Aqk++24HfdE1q%^eKm*2t@K|Il0VK#GA{YazV`N2t5Ro4PqB5Em z#%HXkcTaeLr2)i!6w#8J$W7!CFQo~ZbWL_n`X)n@;mJ5+Co`F~Frk7d@&FA2Q$Y)3 zQ$U0KRKbcO*R&fkfm;_G3L}j82ZE5JP#yPzmVl z0y_H;Lt(^F0x^_D3>6VWRbaIjF%(1$#SlYjtZfCvP}#z6->4t!S_Cnav{tnuaJve` z_KtNThC&uM-wi@kPk5wMhqn^M4Oo?B8I9Ho=Goa zD2Nz}A%@ae3k!&$@}z6Zjdjp(;dKINr?IYzmCy^M3j*n4K)N)Lt^lMf1L**BK817c zj0aH^uvW<=kS+(Lo5dPQgDxu%2@Qs8tK$riu7do-Gvq}S1+5Gu1*FRZ=}JI4*J(GR z$d4$BAc~TRqMWsER)KV0AYBkh7X#AiHJ}Wnb0g>Q1L+w5lR&y0kZu-8M_5rifpj4t zT^vZ40n*I?=_)`v57y8CvW_T_E(N5^1L;aYI#DDoqUB32HP1=1C>vxp)>6m=qs zLReel)=E+U(v^X9Zmg+(AYBAVmz4FCS5g{xS!-x$JZ$A986e#Zkgfux^8o1rK)NW9 zE(N5^1L;aYI@hEdQRGJyMG!?vL{ZLKS*t)gFOV*XY=u{(G?1mI+|wRJQNUVZ zlhY|gQ65oLnx=q`As1rEhZqVYh7y?!kZuM@R{_#_B!h_p=~6(tJdmygq;n0q5kr3D zh!Mn45;2ss^1~{S&I_aq0_kEvx-^ik0HiAe>D*bS`8!J|JBfNS6T8Wr1`>AYBzm=LOOQfpjq-T^dMN0MeC_QM!@$_&$yp#BO}ot5LTHhd3wi#7a|OzoS(7O!eP9pvzKxdBp3}PQUzV=7|2VB6zn*aa+ literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/types.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/types.py new file mode 100644 index 00000000..f98dba3d --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/types.py @@ -0,0 +1,1187 @@ +import abc +import math +import re +import warnings +from datetime import date +from decimal import Decimal +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 . import errors +from .datetime_parse import parse_date +from .utils import import_string, update_not_none +from .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 .dataclasses import Dataclass + from .main import BaseModel + from .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: int = None, ge: int = None, lt: int = None, le: int = None, multiple_of: 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: int = None, + max_length: 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[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.regex.pattern, + ) + + @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 cls.regex.match(value): + raise errors.StrRegexError(pattern=cls.regex.pattern) + + return value + + +def constr( + *, + strip_whitespace: bool = False, + to_upper: bool = False, + to_lower: bool = False, + strict: bool = False, + min_length: int = None, + max_length: int = None, + curtail_length: int = None, + regex: 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: int = None, max_items: 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: int = None, max_items: 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: 'List[T]') -> 'List[T]': + 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: int = None, max_items: 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: + digit_tuple, exponent = 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: int = None, + decimal_places: 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 replecate 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/typing.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/typing.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..0e7e03add204108f60b510960e500a236b6e9c80 GIT binary patch literal 200704 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%0D$8abf7Z7r5 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%0A9w(9^A(6^rU*s;Je=YP* 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/mypy.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/mypy.py new file mode 100644 index 00000000..26192590 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/mypy.py @@ -0,0 +1,837 @@ +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, + 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, + 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.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' +BASEMODEL_FULLNAME = 'pydantic.main.BaseModel' +BASESETTINGS_FULLNAME = 'pydantic.env_settings.BaseSettings' +FIELD_FULLNAME = 'pydantic.fields.Field' +DATACLASS_FULLNAME = 'pydantic.dataclasses.dataclass' + + +def parse_mypy_version(version: str) -> Tuple[int, ...]: + return tuple(int(part) for part in version.split('+', 1)[0].split('.')) + + +BUILTINS_NAME = 'builtins' if parse_mypy_version(mypy_version) >= (0, 930) else '__builtins__' + + +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) + 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_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]]: + if fullname == DATACLASS_FULLNAME: + return dataclasses.dataclass_class_maker_callback # type: ignore[return-value] + return None + + def _pydantic_model_class_maker_callback(self, ctx: ClassDefContext) -> None: + transformer = PydanticModelTransformer(ctx, self.plugin_config) + transformer.transform() + + 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 float(mypy_version) > 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): + return default_factory_type.ret_type + + return default_any_type + + +class PydanticPluginConfig: + __slots__ = ('init_forbid_extra', 'init_typed', 'warn_required_dynamic_aliases', 'warn_untyped_fields') + init_forbid_extra: bool + init_typed: bool + warn_required_dynamic_aliases: bool + warn_untyped_fields: bool + + 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 from_orm_callback(ctx: MethodContext) -> Type: + """ + Raise an error if orm_mode is not enabled + """ + model_type: Instance + 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 = self._ctx.cls.info + + self.adjust_validator_signatures() + config = self.collect_config() + fields = self.collect_fields(config) + for field in fields: + if info[field.name].type is None: + if not ctx.api.final_iteration: + ctx.api.defer() + 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 == 'pydantic.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 + 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) # type: ignore[call-arg] + + 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. + """ + info = self._ctx.cls.info + for field in fields: + sym_node = info.names.get(field.name) + if sym_node is not None: + var = sym_node.node + assert isinstance(var, Var) + var.is_property = frozen + 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) + if isinstance(value_type, UnionType) and any(isinstance(item, NoneType) for item in value_type.items): + # Annotated as Optional, or otherwise having NoneType in the union + return False + return True + 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 positonal argument. + if name is None or name == 'default': + return arg.__class__ is EllipsisExpr + if name == 'default_factory': + return False + return True + # Only required if the "default value" is Ellipsis (i.e., `field_name: Annotation = ...`) + return isinstance(expr, EllipsisExpr) + + @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: CheckerPluginInterface, 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) + if tvar_def: + signature.variables = [tvar_def] + + 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' + 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/networks.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/networks.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..33c5f14ff69df4598ab7c09203f1b3d6d9caacdb GIT binary patch literal 256512 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

    l3^>+YYJUOKUf(q}v5BlQFtRSEZ;Jf+DP*sI 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 MB>w#O8gStM0~n|Nod5s; literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/fields.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/fields.py new file mode 100644 index 00000000..cecd3d20 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/fields.py @@ -0,0 +1,1247 @@ +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 . import errors as errors_ +from .class_validators import Validator, make_generic_validator, prep_validators +from .error_wrappers import ErrorWrapper +from .errors import ConfigError, InvalidDiscriminator, MissingDiscriminator, NoneIsNotAllowedError +from .types import Json, JsonWrapper +from .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 .utils import ( + PyObjectStr, + Representation, + ValueItems, + get_discriminator_alias_and_values, + get_unique_discriminator_alias, + lenient_isinstance, + lenient_issubclass, + sequence_like, + smart_deepcopy, +) +from .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 .class_validators import ValidatorsList + from .config import BaseConfig + from .error_wrappers import ErrorList + from .types import ModelOrDc + from .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: str = None, + title: str = None, + description: str = None, + exclude: Union['AbstractSetIntStr', 'MappingIntStrAny', Any] = None, + include: Union['AbstractSetIntStr', 'MappingIntStrAny', Any] = None, + const: bool = None, + gt: float = None, + ge: float = None, + lt: float = None, + le: float = None, + multiple_of: float = None, + allow_inf_nan: bool = None, + max_digits: int = None, + decimal_places: int = None, + min_items: int = None, + max_items: int = None, + unique_items: bool = None, + min_length: int = None, + max_length: int = None, + allow_mutation: bool = True, + regex: str = None, + discriminator: 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 ``maximum`` 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: 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 .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) + 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) + 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: + discriminator_value = v[self.discriminator_alias] + 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) + + try: + sub_field = self.sub_fields_mapping[discriminator_value] # type: ignore[index] + except TypeError: + 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().' + ) + except KeyError: + 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 .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/generics.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/generics.py new file mode 100644 index 00000000..c43ac3e3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/generics.py @@ -0,0 +1,360 @@ +import sys +import typing +from typing import ( + TYPE_CHECKING, + Any, + ClassVar, + Dict, + Generic, + Iterator, + List, + Mapping, + Optional, + Tuple, + Type, + TypeVar, + Union, + cast, +) + +from typing_extensions import Annotated + +from .class_validators import gather_all_validators +from .fields import DeferredType +from .main import BaseModel, create_model +from .types import JsonWrapper +from .typing import display_as_type, get_all_type_hints, get_args, get_origin, typing_base +from .utils import LimitedDict, all_identical, lenient_issubclass + +GenericModelT = TypeVar('GenericModelT', bound='GenericModel') +TypeVarType = Any # since mypy doesn't allow the use of TypeVar as a type + +Parametrization = Mapping[TypeVarType, Type[Any]] + +_generic_types_cache: LimitedDict[Tuple[Type[Any], Union[Any, Tuple[Any, ...]]], Type[BaseModel]] = LimitedDict() +# _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: LimitedDict[Type[Any], Parametrization] = LimitedDict() + + +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. + + """ + cached = _generic_types_cache.get((cls, 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[(cls, params)] = created_model + if len(params) == 1: + _generic_types_cache[(cls, 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)] + + # 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 + 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. + return type_map.get(type_, 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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/json.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/json.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..8ef4479c92f5c4da93c5a8a9cfff73f4be2d69ed GIT binary patch literal 69632 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 literal 0 HcmV?d00001 diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/json.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/json.py new file mode 100644 index 00000000..b358b850 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/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 .color import Color +from .networks import NameEmail +from .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 .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/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/main.cp37-win_amd64.pyd b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pydantic/main.cp37-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..f55d65964dccb7d529775f244203591d930c6cb1 GIT binary patch literal 385024 zcmd?Sd3Y4X7B)Tv1|kwCqOH*@7&J;;Kon6RqBD?4M<>coRKOshK~W=SG%g^RL>b#r zu2;Nx-Ecv1$33!yum~t1n<9!LuD4@QaRXeg^S$q>>YnMD;V#ej{r>v#JYl9!SDka} z)Y8dpHJ&?>yH%dpCc z*XCDEzWTDsW3S8~H}hcdiJy$+A>d)@m)%9k%9x`!UC26IOY*2~MH~zM^zUn@Kan8M6zN7N@&pM!sZ#AUT zAA`lerg!i?SH4aY2)}3fd~F4k`1B0|ghIu?EMEnhs!q;F`n7^gJIn7YN1v_u9M8@@ z+WPkLGqh6v+{`u9iYJJtHI}5Z^IzesJm+B3(mv+3ct^HGd_#) zne;CRv39Rg4P}fNtFI#(G^Mo*cAtFhWKNLC1hS#*eVa11n=t8WG^C7tkd?0kKHp1g z*B{XTU;hgZHEVa~o7S?BwbisXn%3&L5!~3uXKko&stNRLvR2pro)x%vY0<{Oy-jBA ziu{X~uTB1!ssD}*|9$_kbwO@P&rPNk$}h2&nH%?pi?)UWk2Hn*T#%2?WhM2?st+;a zS!j@VPW0fdrLh66%xEaLXVY>se$1tt+W3;WS-TdaDU2KMZibdytIhhRNc)C3{(X*Ji=k4@Kf<I zo3$sjinKQ^+_2U_CZ=UP_W=p5j~idStGhQvz+kr{e$}HM#!>$jLPO&KCK^4>qGgfn z_&qZKY{4Ln9qR#3g5?0VsKxJ#8;3}Ty_}cYP~%{rYUyUyo+L~R1QY9piJbM{l8Mds zEhC6un)eAcjzn{Ca?jp2zQ*xnAeH<2c=ag3Ho~+VY%S-cHY@4*c1h1Bs@!^e`$!N- zp&x1-MZVgG8qZe*ySM}`POF7!4O{EXSk7LEyx3Y9vbNZ>o^9iUMp=^zf~HknVA4`T zW0qs)zE}qmoa~faTIZS{fZ8PKU%EbyD##l?Vx-c={*ci(kmhOdWIcEH+-6$q!q&8z z5Jnl4${&hvXlWZa%0V&=6*jf(_762SVkphODb0u*aX9L*wM$eQH=B6#4pHRPsVD)# zbs#teYMFu3cR*wU5#|$kmJ!b^A#yhQy^DS&U^GL&*QMW9_Uni#U9!84FVwh#-H#MD zx{F2#6440%LzH4{XtvoWD^g-w*XEh^yQ|MIt($VGfAO}a^{E+eXVxCqDuVA>(rF84 z_>5tk;qI*FLUH#VL*$85$NE5uzprdwv_XezSgw8wOQPDZl}-DV3o`2j*ZB?-d=$ zsriCtEDmrnEILvENq)QwFz9MPIly(eY`&e6v2w0~>uI?TKCn`JkoJLVw5nMC;{=`f zz^mvWqMhy*WZSBb5qD-3uA#CmFSXu{8`bDm-*m$np+yEcx*sIs#z^`!5I?}QJ_#*4 zh&QGQ?e+GTVLb)gBCn}iEtRQa4O{*R&}ZO>W?w5zeiAp@D@xg+MTY`m%PAP-o@THY z%gG%}e*D+G?f1dyz~e-V3wqf97^f*UMf!vm<)Kg5>bLl(Hohg5;H8w4+rAWv%3;7I z*KeynUl=J(Qk#C^=zJzrrB>V0Xj@KlQkPO|y=nbqAN8V0p!cT+EunWNRHeqW-ZHJ{ z3Z{Vuv?dt3I5Z|S>f$kOk`PpCV@}`6@Bo~D8wlC-TtQh>ltFW>-@?{sabqp=YUN1+ zb>mv2W%NNo8W`C`?W+lld^?PQS{1f#$^9vCOL0LE|Az|(mDTSK)b)iAEwxsaAprC@ zYwcFmC(Hjw$^QpQc&^Wv@H`Mm&b{6KVDJ&3}_Y8E38%wFq1N5w#EFP=GUNS~jL8P&b$65MKkOxo&+@yB{c1 zq0L4ox{anoUqD_VTdNxl5=;w7PB2Y^uDgw%(v8Zg++j9=!?|k%Fot9PEGRu&f>L2P z7A^>et(6pIz8NzPnCSP}hg~9y(tgREP?2UX7DNKgGv!;(J47DyU-TJ1RzZO=IY65; zfY%DA{}J)dMo>4&=Q6;w_KO?$t%6$5AlhaDZpz-5s2 zfj#ZUuvxlTWp3{FY26ccRBzlKo(ld z#BKz`aC``o7NjDuBGXb<6-E+MWdcWq*>kO3gXG1WzJdmtV!dnEX39rYJdh+==Ov+v zo^jLq(X`4Dn72g=A-#o|El6(#gJR717t_$q@GP52 zcKgMj@cwj4BPGSF|29y6u&CwPI>9(me12LAG<*f=NknbG_@6|_1*7($FhqamZk?su zUOLpSi<@O8dmZ&1P^IvJd?8TxJTSKOO}k|ozKwp&FjZTk`=be7I-6FnP2WNSJBgdY z{feYi_2RT}Z?!g~t;vliNyl7{;?g2Hqr8~8<}Hw+imMTR!%S>i{FxfXC{PU}aK&=^ z!##x>=7T%yefyI+qJJ;A87Sj@HXR`*xw;^4q>lLch-1wkGmgcJt(>l3Vu02MA#0Us z{aRXElb;{B7b~^5v2Ls1P<>h`{V&jGhooLDHxvA7z9g5FXYZXpipl&T?$mD6c2s7tQ23DYuEUZ`Va>mzQT`-pj zQJ1Xb3gZdjQfY6XPV$PFUtCZ0Vz~E#=-9e=#uA!ZadgQve1xO7nD`rnzkK`^;;#q( zdgCvM*izlPG~PBGy}rV%|F*h~87~3(tIL^uwwA1Oy&1i}5^bySR}(j;a;j5x#ah)8 zT2KhXYze?IY+l;Nw;-Qp8gCu8a#pmUM=a+n_?l3|GB9MH^GG@lE-gkepiE+*=V@H3|ZgP%>_f& z9)^b=CDxu2>-&%u?{hy}SGVig)cn_Wl-Lsms{z1@BhnG6OBO~DS~L_RYCb=kbb`59 zsX~3i1^H(E+YvaQoEMghGdPLyG-lY_@IhyAJ!An4P2Uj1Fk;9N3?VL5v(Tq{EWTWW zR@LRDt5$F!AC8VMzyd!9Fmju(SNUY*20?QH(X0fYT<4qCv>jlTEql|9E=RK=((EEO z>&RyDR*3J?qRjdyM_$O5K_sr(;i9p*fmk`JM_^;}GAx`AkvfER;tr}pX?%sS)6(S} zYtmumb**1iuxacV>6?@=I{e1fYL+TmgD1w4>Lt` zt^W~$pX;i>hZIpOC&KUpCMeh;dTjlMD@3ZSQq!dRS^h0sh+mczkAH%%(N0gS zBTtF4N&yANv9*-}thW~iHBoq_Uzn&`ejjD57pKV5Z^8t}tAhwOxe$i9s;%_ONsH4m z>+C!k*BX1_h3Je(fK^oFFG;~5P-=}pn>F^0B^=MLGV6QEb*~}KG#8W8K}I6-4Ql^o-ob(QyJ|H*_9frk#d@epzRfaBV=|VGj(lH73+hh4V-zAK-#j+N zyjcG0-Y0&M@3U0oXs1bFB3ZsGI2V*}RPyun_C;rDqL6Qm!2EN_M{GoP$XX8*WeK2r z*t#mO3@-T?EJq;acT4G+q2^vOzsdMgY<(tcmLmT=(287dEiI0PvdpDBTAQ(9SPGo5 zA&hW02uN5nDW?Oiu-}qdR_XiSfQ7UUEUmrLCyTQZEY8-!Y`Iv&yd*EaI5lO~ors{TBTB7We<@%fYL2#3B>x*8Xi|Y&#)-KJ88{-yI zu6rr#x{i88?ZVN@JPhExX!Q<+f~Iq#qjuzrKD>)Dlvk5d!yu&pm*CxS)*>m1KN-3cR44y#MO`*F;c=Sr<2^pog`! zep}5YrV_GgN$E*^BLWFhnIpm$T)&Bgw|Db}zo{WU!66o5G|;tMsU=*j`fKh+!k82k{z?qF|=qYzwQA%wCHty-HERlIwklwUVqFkxR}X{_4;O0 zXwj{_ep9aZ^u+ZvUO$QJxbZz1fMYuXndZ@pDEHN-)zPkckPEHqo8rckG8qhzmj53R zi{g7Gzd3xfP(3(Xa(4vhRnw;tGyd7fM~M(43tLY}AU3T#3wW2Q{PT~%IAaeMFyfb5 z7a`)oF6Cyb zU!bM8&Yanr=rz&QTY^-zing#El^(HNQFvb)U-MUg#^bC{q26y={So?>LD=1wFo>=W zTQgKm^ljEeH?k&L+<+k>P~;=$8uU57$8wg!O)WSnfQfI|ADUoqoFz3}?h3f+u++bh z4_6oDa;eh;#%5aYgkpnR*+)rnTA~l?N&SBR3}xvGU~54LVCKQ~{=*2V8G`Z~Z&2Q} zMHVyrHL>d@=$b00uoP+rgU?Vy04$o_skTrz6au6NzX4$>$Ulee9_nrQK=72 zD+W>eO01s&<0_)W`UAmt5emd5*3NLWWGftr8J%V079>#2C)(feAMLdf;yt{`TT;1OCdx(YX!MWp0!DVAhEn{Hwqp+~b7a_zU8%3V%)b zTaCYL{LRE)KK^R(X9CeQg<*#JpmG2>TYYR$A9Lhm!XVt3Ctt^-RDx_1e2gyup78}0 z{14d1qYQ=rD(xc=X^p{^NW$0&(%bVIW-2zS;AR3F-{y?Qea*Mdr6fw21H_FlIrU7l zIr%xU@+pm5(5!ikv>`ZJG7p&gF*Rb~?32@X1;Y8UfNgvWF!&F(cjRA&%NFQ6$eE%#AM3Cb-fn69 zj;)qCt)TnSl7_f3|MjFX1Qt#wzTen#Hd-PY8F%Xj)}Aw&TX5-gdQYcL>`Z=C+dx?fq~D=+VQrPgDGAcIw#SD0Z+P z7ac7`l1in82Q0UX`g#T@jSJX#p)^JlPv$O(y$pag+db2$I{24c-JgP(3WcELHRXET zY3xa4S2@T^tu1k*-K$c8J9(ir=*0$QXdpGnq6{edu*C_20=P-NoPL*-1|=sWWZ`$< zb`|bmvO8$uZREowlCK|gG=M9JoZZx#XbHlC|Abf2Pr_*zev6juwRa_pMx%-n)fl3B z0I0&&FfMbjO;zOY55{Hv_7eJI{bs#mt}2<$5EeJi6O>vm$(Y6y(_qb1IV=DU?WG-{ z!SZxB#l4Wclno0VlHn*axzc!6NzdKkXk>QC+TGF`-#Mefl*8 zd2&z9RV!S9tMLoltD%hDm8OmerMWrxM*FGa_^{5hnxsbIzFl#w0 zbxUPp{kAMp#Hn&UC@cRE)9> zp@!B%ZbRI73ZWB|Im5}jJ4llxN$Lb|z3^*S&2mJ(CL6ePCNvTzupTiTiamq!KL1}L z@4qAlGY^|mGMJM#dIpn^OBu`uly{ahn75U@v)DLhT!GH^2;38SmlnMhsCy7+W=v}e zq;2$?k4D%=oqMusP$N1rP8x6=mcKQ|NcJnlP|iWp3QZq|%lb{+pbeqqmL*!x=3)X| z2Sc58;e$=ZOwqmr%h@&dymKLTtSE-z`_1&-xQ|9#MU)w8Ct-$Xa*&Lf5O52DJ(MbS zO?mh{B!Q>)hw@p=?Jv*M5|9B7VV9JoHQkwD^s`WOl*!YoZy@H#R2;!#iW{su<>0dA z1bEnc7eL(CBe{}beH*Tz`rj{>so07}_8Q!iv5uZ0+`mXw!1;;S)I=P?+YqCgh#Tdm z|CSe+^$*A{jz*@HVKLmt7b!BWp^1sWrlc-L;2@2XBODRM)wa~~VUe|}L{77XWW`L$ zL*8;+r1~YSS#baa6wA15j?UU8+PwxTqLkEQv-ojNtj#)nKo)a-NK~!*dcV?W zeGBos`vvyrJ$LOWl?rD*31Z$JY-?54GI z4z8e`e`VvCaX7WJTX(N^!Y@J&#%<3l?VO6P)J{|6ezV;4fA;LYwG(Q*srrA{&Kj+q zTcG%n2_jRao%MxUL#&bp=xV;w5&>dKlcX$KLqFko#4E7|#q>*QX-vLBOOM5w%jU&6 zJ^(FU4QhdUt{PIcG*Ex5KrwR7huTKP3=1E<6(0hO)|*~F>`E;)rLD&!d{A2rL8qjt3g$$;&`BLo1j!qqk2CapA&6`5Vf{aQN_nbi#I|qhd01y zCo60PJi4o}6++HF=%ggc)s59mr~6<)yb6mL*+9zB*vJgH^ajsZpiEunQJFr4ec0Vk zNG9@S79~@bYg&k{*K&}$p7pBSNQ$f4!Uh*x(ikwV5qYh#Tcr%;I7MU^h;;6wi2OM)S)Ss_)9`_;%uI^F9uN~>V?S_Q zGKyJZCnbAPbb%E2mdXiBRw@xwgx}_8f5xVbtUB(Hwy>$E>G>z#=hzzIjZXm6tFf4IV!deyj_3&GjUj>j5tO9*5)|gzpBoij}`Q@Tr7v_rM!(28^t%a=|mn zVU-5Y_kbmoT}3RjUHIJ&_OXOd^S~P~)@UZW;Jb)@hz1YwfCc*?V(II`-LZxUKPnx5 z8sY8J;RfM9!cC;OxPu7)$c4KyZbSI8boj57{WIzCt%To`4&OrfjV|1Br1K8pm!!j2 z5q?fOyn*mj(&4WYez*%4b$W=fwqDo+g#CyUI|+4cyqB=;Uf4Z^y#pBH{yZo<;v@^X z7d}Y?MF8(;KXscFa)-u^Pv#PsS`=W>Oh)PdRyy&#*wDujJ{z%@!*Ej$q>)0!2blCV zK22GVaQTQ5b}RYl4;URxxfEZ@fx>Hc%ti1g$%RqYkVEZP`Yc*MPH-` zapR3AR3ADY9z*VTUUHwmvrm)m^D#^&c@=*%$W`Bf;MejvzF;#VX%#;MAmux^I*5P4 z;g*F&DC{(@1Xh?5nW+V0RTyp9f%`mh*&Cd!NOXW_SS{^QqF|4~30D3rwLU@>aR!$7 zT;EgTL64^uUlTYoD0nBCmVX6@Y@M5H_8E{JIY}+wHwI!VxDJ5N{x_@lv()N+X(0By zM1$hx$fW7IGc4W@f^(05pl;K%KZYLIvB97-g>Pd5w1Bsnl-Yv{)U;GMae9Q1^Ur@w zEvZadQsGp%T2djY+Ejg}cS%)2%HE(WNhO;egfkm+#cN~vWDh+PSsf1b8TYuLe7bUo z($wsyrW@qa4ELE-5De5kr$bUIEr}M$eC=0Y6WGB)yn3j2+EHTD|J zPLgIOj~gYX8G-sSvUZ2ND78L_8@Y4nMk1&2Uh@FlTFBh8u~SFb{kQn0E)VA=pI1_s z9eBB(mxyw{#uIqi{u!kbc{@l&*XVJwCAQLy*u$$wa%36E!`pg{Zf%mEc)L<-`@eC1#6icm27@fM&d)97arK1b z`wV2j{=av8C>o$PSp>)TvNSJVwQt9V^9k$Yn;mghkH(I8nCD$nod{OLrPlkLu%+-o zZu_HYDdk9faWihLgw*Ig^HCgbti!OI9{~f6xAGf9THJULGI#WK16pf+?R1Oi>(y~% zD1fPxwvT;AOeHi^_M_m4CO<_N@h&vD36yBi<@W2H-B}!@0_y|h=YH}t9|=t3jrfKM zYr9fUFDM1-E`SNk8G%6kdHjkkY;{h+)!nJ+8;%9D#TjCS9kOh^+AmZ>eX|TeF!5d z70TnGg~NsHr+mUY?EC|AD@guhS(iyIIP|8jitKm=n&4JN{2Os8<6mJ2=Hxb#P#oO<9^-7OQnr&yZax%vAut*-RoNq?U zQ8y~V6jkQOjZ2{?j_Ek_B|X1p&(7${%4rZ$MWkR~ccf}x!MrS)lFjzt&Cv2omsa|; zBc5ThJuSu5CviIze0rCO{yJ2IDEA6oavFsil9ZfkS>sFyw;Gos+#+bKed%AcaJ%6O z!X3fJG2=*e%N{xO+I3qhu`p9FWx%f5TUyD0PGc#g14e3&mz+9`?_NYl_=& z1&Tk@3&f1Y=xm#sVzTxL#a~Hr{_T$RV1JxXj8&?^0;Df0YK*Ig7y_jqV!Nal@!0g{kDQJNvWw0pzXD@{Vy6NKOUGf+2F z$a6}QJ*0>w1!6qA(%z`*Pu3bAgcO8n3C z45i0^H59D9*W2UiIiUdS?Prpm(|;PoJO-vzWk?%@OsnfDhR+d40gsTuQ`kj)Wb*63 z?R10M zT_)|B>EuoaDPTko7DI-@IwPaPJl_~=^F9b;vg>DJ`k*x7Sbx-O7f<8d#%9gnoJODL z2Qn_ES{EOvMo=MX9;zIA&V~Q%gTeoRo6)$)e;$b75dmqSNPBWU9;)}yp9dNspy|(6 z^yeu0`~ZFX$3TL(lNbr%ToQigCLa3FQ0{^t)dM)Ob8s*q=T3zLKE}=G1j!*pQm>J8 zkmM~Ktzp8(Rh=9WV0Jf-$=vX*cme@Qn|IR{PDwUh-AwM$Bx!jV?m}9JftHF9$$nh9 z?=%A!LlrAe33mP!C{SxdortxVETn3%M8f!-gQpX5DJh&Cg%&=Wqc!v+TtP$6W#gD} zBA0b>+@mIOejSdV$0RnMM2;`JksLDtvL+Okq8T1LdP~bQxyOs_aRz(zk{H3@q`7B|Kfj;&zyOk z!L{Xodxjsm3r?gXU*qdb{CSVzHm(Zsz0Do!d%oRQ7u3@RG=P|YtRaWP=#9BL_}5Y7 zE8T0$h`DVw>|Ww6=`G4)KfHhXgucw_8BE;w32q{@{5zv)`F~x$A2Sow$)0`hF;FvZ zU!3cL#?t@c=6?~r9pw{VFD9?wT(4#-HC!3v{zj7WEKr60LVGpdWb+mrmk`I3z`@lA z@;Uz>Gjtw1+{t6Z|1ponoW3Tb!O>d`!=CT%2QimDDk+!6V~55adf=vA>3S~YCl%0% zKRx5CB5&>W_`Lb8E<=sHeILWRmR;9hr|dH5oMe<7);Nlx2S-Pgy6ClOzHlzef%>{e zn{2!yt(%CpM$o3`ciI|E`j|aJooq8&(D@s%g~mizM`#vjYV>iwGn_oJhD(6% z|0z$bQB@hYATyAW`e~SCWIO~_h2iRBN(~Yy*V7GS0WoX7ij;)nj9n8x+}e#g(f7O- z3!O`#{$2<~Woa^&hd7qMR-vawpRK`7YR z>Se?318J-LBt@1_lKz3D4|9T`(w6A}ms4wMJW-F3a@j*uHJUzk3V&7VTs=?xFI}62 zUurZ}PK~ApgE|<4Vsz(LaWS6glcQBRf8Gv7;ZZ;&)nu-UX901(R-}$IS1k6!k>Ifs zuwpkP3E87i4P>B)W}qr<5LM}!y>ahdN=3i)XH?O}#JGJjhh#j8Xd}Bd>+RDt2WcW$ z!uBtqeJUyOgDT1Vq1H_@d5}nIGG{T-3`eKTU`}<4H`x^b?e$ZFO;Sx)g(cbi8Ws|{ zgmMcqw}W!nP!3t1K-kFm0NEwVqf$|1oos*{bO)ix`gXQelS>~JsK3Wi;Kq#@*g|S? z^M-5CvdF&;q?|%tYGv^mQQ!mMh$uKzJU2w2hb8sVOA|)wm+~!gr z0_qv_PO4210;WhkGcWo?#Yssz0I6!`rmQKM>NxD|l5Cm>`hrustxA&>og@vNt;)5e ztITSs&HGYgXg76O6)J=u{#RvxlO%DEHh)LLmw+%w;H`{{9T4nQ3o=uIxw#wLNo)em zDGBmR1vs7)!8y{L6}%PmmmwU(m7m8CJ_w$J(JN2&8YI%_GeG*ESJQj>`_eXJ$iw-< z0@UJWqcDLjrPjwOc_oK_>6^vA&!R8+gBqoJ8Cf?=$i#oBwar0-KbtulYi#0v3ONt? zZjH^f_mGw~Wd|3+2OdhUCRFL?QKZ~<=MmH|DYxPH=LA?~DpAy@nq-Ski)D0ErZ)bs zng2pwm?Vjl4%Sf$3xD$O0D=R(7xEG1^q6rAm~+W95X7> z*?tB0I9BRopze5K(|8@xh6zYpeKROGe?3gd|2oSh|1fe#AwT-g1bIC8dmb+3;CC;Q z-w|)EiVa;A`5tVHc}8dZR8T;Q1J@L&s|S9mx+77+RJVdCO4MFb4bCXYgrh{KYVeY; zphWlIY$Yv(hs1D@^%Prcba~^6v%iKs~m~(9`SUBM~z?tB|BX6~y7idyo{U z($5P;0zj@e$vp|lIphL$e?N%B$e4oABx)Et1NCcJzm3DJ8!0Gbbpm#;ytnsvl~6 z6PMyEcT9&v>iN5NR-14IU-pumhO6(_SFR@SIjveg?caUzHQMiG+T^(d}`$>U7#dQcn z`FpPj&vQihZ7syK>sKwpPjLki_D~`mix0c_w-gZ`(ou*UTq9n)2WECDhEGQKrEw`ejPhwPDg9a;`|&+mAtWR%P*!_ij4edv_OH__ z*RkGXwXJa}R=a5`)M^T_sQnCFLFK+eFIernRL6~)0%LZd?o3e7lf@+CK}b#~8I_Lm zxk-j7-+zuig3e7cDihJ?ZYXtRj0jhy8TIoq%}_Hp^30(+#AeOohvW0-^2&YyTfmMk zM5ZQd;38_^$%jA#r;S55y#EJeoVf3eIuX1RScg8WU{@>R(8&fxwh14}(Pl0I_Q_ga zN(<}urzU08LV_jQq=)>fW~M(X+JvrE%878YL8jnQQS4$WcG5$Rl}UL=Q0E;w)CAp7 z6BIpDp{6-WLV>zdw6&y1KGi2h3CmVfGO}!fJ1JS6Zevi604npOcQ&iy zi3oB!E=3ogybk*I!_Qh5XX6UGco-YUjP~ekm*CZ2oK*(eK;3xdVCS)c()PEY_(EaS ztsV+xxD*Os-UuvrI~2Cy3KULaWin=gh4aCtbwQpS zh)@T~oC6Vv=j`RRZp=H51#n?>#Q~0s$#@_F#`A&QRr@da2)qZBVVEoaK;3z+4y9tp z-1rXzXX4O=J@-j(F~0xqNpDF&AX5FLca`19jTw2;yUM@WMpGCU_0c;s z!??oPRGo|c&n6BN=e;^Wq^L^{*Vje#5_ACUo=L39^1DD7V#=CKhLav_IZmDpj~jW`Ins0=$z-`Ym$isd zT#0b0Bf|NN_6ZR_ic1mU%xfX0$G_JiycJjQb+v39GwLY9J-FwY)hlHXM%NnLJV)PD z!#gXZ>_lvMpN1B*I~D(uu^2~Ib7yn~-nWAW5XX#-fWsu9SjMy0a3GkBxKW|+qI|`> zO}J}dzV+Sy`tFqqr|MVcv!D4+F^|R6YEk*#(!k&TN=yJ9HB?q!u?43HwM ziW{TAH6?Ve?&Y;~NTlaglqJsAL1gR`j2nfzPiyocUWnhAgi;{en09+@AK(*;xMm;6 z$uu^vehQNqFw}gWp5jH=1SEe~Ydl{5grVlwVC9bSZ9!esKK=f9oShDU@~F4IRG$qV z%P|z3Rk!V(Y6caDST2I|)pph(#|VcDB+2W!p&-b(i15gWz|&iZ2#+&{E5jIcw~h!` z(_JJCqXL&=7<($A-*Vm2p(i!AELo-2NJ;<}ji4f7*O_d_o~PuJFVp<|CL%JrieRM-!Di zCA4Xh+VawQV6Jck0Ve1Jy!3$eQ*r6`0 ziG3RhYwd+CBJBGSjvS=j0>ZYru$AmP>`=f~d0~SHd&PyVV!MHaJ>rG+Bg}GP@3388 z!mjtiP9$uc3ln@t6L!8Ab~s^0UKlq?n!9>o0m2S)VKR<3gvEzD;}uvIVJ$9f3Hf{W z5Wqh0!k#8@-3jr|0h#XP^Ulx1yc#dqI`hs)DR)G#b9tvJ(;YwWJeldv*9Pv~nQ~_x<$Mig zKRMH#t9hq9<<7h8b2smtnd#1*yi<_r&Q#uMpK?bysN|hpL%lLsKswvV^_EO`w(`!R zOn2VloySt{hPbu(!Oh!w7rHg}uhU?FoAbFzmhhE=Ndv;42;OeuVo)xLd>g z3w2pmc)rIy#+?cTOJ^&11F<~GSs5uX1vc2Zam*humqir9Oz-n1*SgXyG395%Y5)XG&aGbIr%jd?kO6}~aIM2td?Xe>%pV2eJR*MwpZ^X5J z$`1m%GCQ3ZQnuB6{6p}f&4ksN+6>>N@-*V2ob56!_?fBsL7*CEk;?Ft*?aa=52zIm zhm4owbR;vY?XhP&3EF)ENlnl~sx--$5Z=4gz80-@P6Hf+q{rx)Ee2jgR_?iVU1v%k zn!}eyD)!5)&sk{6O?}=SnZv8dpOuQJobSXNbk6sR$}*hIi6?L=Ip6XMDEfV$Ya@6K zSI~;v*f?f<&-KnXxTlOjuP4@Z;&@r;!boH>BOAwzB6POT)4TA+HLg%C2 zjT6a7Q+D%%Y7&y`2dq^~Q`tBPVs&A^g_^Z~z=}`k-1l`-RtoQss@g2_RLDFaD_wao zc}mg-cde^t(=IG_6sJ}m=fEM< zgwvS|n5sIk@Nf#|CT{G+CLZ~^M(%ORWf?uH$QBISeiydL{;&?<>?KYs$>3eZ4k{Ov zY*bu@VHWXbg)&)%VVyor(|Z3vCEb+8HYdONM^(!H1VtJxnT}XSiONmC!XufF_!S^Y#d#(o8ra~AG-rl0}YIi_I3g>n{?M~N%2edg?( z;W)7}e-UuXw(Y*=!r8l(;HkH5hePEeBNN-U8{p9r+qPTj-(=gC-(=hN`5pLXUkYt< z^qzaN^t7MQ({|+1B6`|$Omr>s3x3(O#f+!ynQ_zBCOvo4b{FX-Z`u-oM~?QAW|kI_ zvb9HL1CzRw7Hq`Uk~VFRLrIj(x&^>u35qI>O`O80fF)+wv@O9jpf8^AN!qjx+V3Sv z0Kbl-Xn_r!^Ps{OTVJgR0y=My)+)}mB% z@Srp`#*Wby$JKFTF&fZTCgPSZ;C=&FOv6R@NA%sEs$+u+!$G^9<^Yok`}&u-QU7l= z50$hXiZ_vp4E~$|SV9Kh<5FaB8k4rqwrUv^s-$fr8^?@~kRRE-G=)l`P%F+HCMD;r z{JxR=xsxrda5)CnH~GAC%ENUP6qXy#bV&`!k+!VgFMwrTMBS+@R!5z4Q4)o1 zS<84bikr}}S=p?T$|)!xzCqIou(S1qVQZ)l+5u24ylFkJb1PuU4)p&Wr`p9h(-S($#2nOa-fJPq8) zf#sL6=|gliBJ#aR)rf9?eJ)vq9e1CktD$}6QB7)uadiAJpLr)PVdR3^u1Jzgpzbbx zP@=|TL2Rk|c)_$`gzm3k9-@qFhh-=C6REGqX=JGeY>dBv9n{0)RrZ)IN<KsKQ#;PcLHWV;)L`rYHH-q-5aXK3cP|COL3Ea?>dI?m;I>WYFet zWVUP*v>QB%G(sc(FCAc6zV^3pIA*jYKi$7$p*zp{dB)8gGxl88**&MLJ%sf+OdwyO zmRtVU;s3M`c^2y|@gdJ}Etl{i58zUK$mfILCmwoF`;hl=1wT54jbp}DT=@NfdsJxU z{7wfQjQWp@Nuey?9-!|AMK4<6t|WJB?B9IK4k{d-QSak7mZ7JeqkAbMc|el8)C4l= z6wQbs?kO7RMaog#3ToSbK1D-qtH^YQvlN=3Ud9~Mr)YXZigZ>mo*JBM3F6W{QPYDG zj?H2d?N01L?N=Th=1FU0!=b*HzTg%*4USAd3*Fct+D2xjtI4vdrs~fxy&>!+L&wwH_DwP#5x?x z0RrRGQOY>PNbSD@EuBVp-N(x}+u%Wgl6=KP+?b60JvRRuyeCRy!{<1!KPiVP%EpsK z2UQxguiV=j`t&hgcrg=w>u!TV@#TZfU+;9@V!R1c*!U$&aZmMg6jWfJ5%xDP>{G&S z0jv>v+~`vJ-$7Vubn zy&UY|0VopQ;*U_+(i{Hd=JSBRXjvpXe$NbaZo%7LjX^0e#0BF-c(%B48}DF}P!WXR zdE3L#u?|B^&Hxjk{7_>&?(@wHMmjCEvyNVg-@lHuTLOr$r9(iRUvdodh!6kfV#j^UHwYiPA#22%Yr23w|Pgyydk82a1gO zlvT=D>QZ1FO9d*;abp4Q2*ITB;5XyAwDjZ;J0q8+gQK1Q#}L%;Ih8Mk(}!Q50^{(~!E(4c-IY#*PlniC%cXfe-e=`Rs?_>Ept; z5zjIQ-o*=Vbm04W;fo#k54|0J1kXYT{-GECrUPHc&Q8jgz&=;({ec3h0BuWItPB33;&w!cRTP_F8rT_cRpO>X+GVN zgTVjdz&Co~hdJ;!0e=%G2w-Y?CQMBya*oUVhRBPY#&@DIwEe~NQhhj-Jm-Eu>BEus zZAETRC%&bWhL1CJ;=>z=KgI9enF6EXS3=F>#xmYfhK~iG>%)bi0S-gIpXT-9o#FOs zceML=PMij8YVX~)3@ochnmK|!;<-#XZYK&E96%xp?H-suf_GA29Kn<0I09eF2(;C6 z1Y-5)Iiu*MMv>&T+gO`hx)fVYAq*xYqgkN*HZHOj=$N!cqVLfwi#|y9-204QuKP0K zzHWy5TEJ=7j(jI$7A2AMIlpNc!CfPdvhU`(EhvU8yi-SUfisG$dns?@&0m;SS4rT^ znZb=2xG&S5x=tbFlEHC?&5l^cI|w^#gx;l>u#|9LRd8S5zpLDrm$LFsF4~EL7SzS< zEIZXP6EUj;9GcH~;rlu8d%W;J9W%Vq3;)Q0U*d&tb>QcC;aeQ|DPH({4*YNz{w*zW zio;Kq3;&Anx1ILi^mN9xo$!SYe3J|Rl<=1w_yR9{o&$f(g@4ZWa~=2{UijY~_+%F@ z_+t+ILKiM>ZH5Ey?}bls;KzI6qa1igFZ@CW{@W?ec!lm@2mZMiZaVOHyzsLf_{%O_ zhf`wszczSIlb zLf8-&wvp{t5q74)@UC4rnbf0rQ)Zw_JdcZ?as-^V7t$xmPU3)aU9Y%gBw&ep#ZX*I zz2Y7?ar@ilx?WMo1U2UG#m1=nqO%=Zp_~tn8n_2Az9&-;z_^;9?xDO`xl>B{z}|H= zwn6X{0L}|sr13*+e6!Qov(!}Y55)T}j#cqAjnE_P8fuvMl3p>h zP)2nyM|I^1=v(Bk0jdA=iW!HAX_fFoll4@ncP91kkLQ$Ud_4id zQvCC7iV$2W#_UmBLModVLYLHwlYB+Wj|Wqy@>r6sNhT{VP6~1rL?kuLqn#?JdS_D7 zTV^WVmnETte#=ZyoT0EJT-bFJryF)u;_bms(!faubM4Y zu)@=z?kPrfH%()11QzMc_C|dYxWLelOI5#Osg-JHcLQHLm`Ex z>QaHCnYB7LvX%V;PRb;*7NHuG`PWn{&Extc{Wh*j>?)f-1X4ld8MRXUB5ds;Kg;H? z^nQ;+1!^@XsAmy%D?u&klbLJQ{+d;N=G4ye9zfd%Zjzc;$@q^2srt8T{PtsBWODaa z-o@NOF9+vAz>)oVvIH6%%5Oovv!ipBCqHh3`9--Gzc?$Ox?{4kXcd=Y|LDDDQK#4C zp|<*IGG6wAZ^L)C6Kf0x>i?!vyCY=vEyi)!U~L?^O!pGT(F&Jh9D@+U?bdH<s)P{S#DmyeiV{Ib)n+wzgdmSZb z5L2#R_sv7Ha8rA!r}C5JdKSxU`|b~vXp)`WAC%)3;=W#R)3@@+n2y$Fm@IQ?yOnLv z)qHr(5N{NwQ^fD`iJr))-3gP<+t~R4>1>?b7wSM|jT=v5Co5rh(()6w{PJiHS6IT7 z#f`g8SH2;6Zl(2hwtih&b8eHBSV)ksR4~-~P3&Dmv*eeJg?0XigDm&y!6ysqPYP-$ z>6|BYjJKhv&Xag?Zkk{p-4imtC?_k(iRilX_K{<+Kgc zGbH>3>g)bguYdQ}Ac?Cg^RIA~)qh#tv9$KYf>x3JOTlC|CQN=!4t&~|9wHn@?*NA? zLQy*#Plqlw_sGY$y~Qc^^fnDKEvU2oL@ElGGQG4*pXnC8>K13Bx%q&|%zMVu6) zuCRB3YQm_eg4(4sLEm75|BDH4pg%KmT`=dpUrYH@KIl@^Z3!c?>VB+{;6FInljrhs%A~ z>);bT_S#=A|7UxxP1tKTv>?S^=YWys+YoZo?G>tadNW2B_c#db8ojan$NL$$9>TBw+v8A%Aj6SF7L0i=4Hrhq3zDYLa*RbvgYHd zlIxz=S@RLNLe@Nsjbp}b=xle%!1sRS`*kuBMRm!vW=#{FEX$1>mzZ z7ve@7Lrf@waIlTdxog9DOEF9t0J2XE1x{V;)L!(Wt$5^c>FP&t&9uVPqB;gfJdVd+u@R(|!P( z|H@+(2$3;M1)Bi)lci7q{w>u`AVQhgFT*?9{$;43^{Ku6^**E zdnS#VROo2bW4d&nZ03UUP@=pLC>=8o>Y0H?J&z$KG)kHu#^xtzp1m_p1jr?{Mu}Sw z+LyzGDb!@TGWes3=<`D|&#secdx8(8v=5C6!V+w4364hXg4h$xi$)ca=2e3=5W##PZ3(i4p#u z7-5fe<}P6K7tlO?gid|Hj&ge{MdA3P-i_nf`5K`$sbG*)3X!|vJdGZr7+YYWw4K1V z{4JDpLR!m>!F1M1vYf8A1Op32(<+Iel}6yr*>OsAFXrO7W0LyA)lY^E zmxG2`)N3L3jPOvyoCwbQ=lscwnE!T$OuR3SAAFd6p#02jznMUTo(j{Q3RCmZ!m57~ zg_68jR}Yo5Cx-y+((rr;>A&iSIPWHs?e0*gLJ2dbpf6j1Y?7_+D#w8>~+8 z^N>UJVM;r!<;a(je?WN5Y!~BJVl;{6Z6#((mbXcxu}4F0>{N;$rY5!&MFQo@eJx}& zKTxh~O{f8Ff_4CP^mY!-%Gv)YJ;_;^djwDYzMe%mF0Cf|Ma)xkj{~7RbMOu8Ts|L; zb?$xmz=Ym(uGX!6@ngj@3sI}#7rAQgy%je;;tyY0zXMEC&hT4vXA8qYENEG{g=!xQ z_7A3N#*7?>WUA`0E@0;`RQ1K=yN1}~&d(r!kdIc5VFXmOC2TfWGhxb!cPTnPWRo0^ z%kj671(Xx$2PKb|=S%61Y?*f5lS;vbA&qhsQT`doG%gr)mX5N@TJ7bJDFkAy8o@h6 zuvjB7J)!W;Hd-Q>$!tBGWZHbFzxh^nRcu3uWjkH^kwh{f&K<|cp^g&p$Z=S1$A<46D{0STH){oJ6=a-$7 z06e1;RTsf}z|;mO$*qR)wjBzp|A$`iza}-l>QD@PZ%&uY!<7$OY4VY) z=&W71f#+*@A2+gbBW0WVb3J@&t=gtmLu=I;LtBjpA9yYm^aAxSV2aZpvQcgz!ATxS z$Tqof0+Vn!$>rDBEZzqvi1o>w*jH%jYU2^FxPRHO|?b@zgyZfvb`Zp zT&U7Fs$Qj6-}pQ75$tUGyB&$W2s~$v37qX{9Q{;u)=Z^mgyJS9GkJEg!nSXGB;k?N zk8&$L>&dZKv`4oh|5cz9sDCn}p3M{o-z|5vXZH?UzLZm(4{kd_GosgLzh6^&oX_++C!By9rb|6 z!yn1km$CH-O`sA2dhsyk!q|q8jZ^pahp^+c*B|afrKPEy9jmnaKq=MPu}XW&6Ch9F zGRkDAS|=Wat$<90y9l{!Xs3qn6&^83w&(?u^(v(FHh!a5-VarX1nC6$KLnsxq3H-f zuknLMhF_IVr5-3bj&ojIgs=6sjZtWZIW{=LAsSM-L2`+@m6}$Z4_deeRrAA;+ zUMi_>-ESzio7QV|?|~y#u0FplL3pI+W+Wj|dpmaNZ=)G{viK{My@gtru#w}Ia}znnxU$$y>K&pkQpr*M2$Gu ztUbO}1ZIYx2(#XiJ*2WhN`3frMQy`0um|)zp=-#tl=BR8Zmf-RU_st14>@6_A_^Ds zyl=Co_xbC6D4gj&5u5a0`P1PbBIhOEj)6I3(NRCVznTt9eoBVl7&@biH{hFX{=*qD z5{}CkcBPGM<%DC?kKQs!wAZFaWcd+;t)$?-4`T-@xbMS2vL=A&Vw+Tcgv(ZPrBMGW z@tOxr)25B0G@B_z_2}whhH`swWokmMl)iMvNW=EyZ$wI$r1!+bN$~e+RN9NI2R~6G zfk)KSUY#`FK;1!_la#y&On_kO3XBk~b;&v@v!Aem40|5ZsgUE(w`&^JA}{w}``*K} zeo@JJ*}QZC!3)mM2yMs+&CLkS%LuhILVKh`%j$RIZ8NpqTSf5m;Adkq^<8BMyV9G2 z-Mty18!|#O#>ZF#)FD&zSku04tlr0svW$4j;K9?wGJcdk6SQ|mXfPwRDkHQhBXo5} zXm&>E%#6_djL@2lP%{%WHf-+$ou?&|y3{C?EJW9S}V;`c)q@@L~4pXB%Ujep0-!lMCD1rC%* z%KOsi55w9CQ3J+;r~zZ?4`WeL1MBDXVeRuBCK)G@nMIl)Nz>dX&5R03KbHZ|dTe0z zMR>%s%GMS;|J&BS=83<@<7*TD%;>0sY!eTU<(lxAc_Tw3LL<%Eor6s4^4!44rZQ`n zY5f?se*GzM3zu$m{l`H@ruCLt|1JD{t=+2nAQMm01?mqKc>jDlNz=40%p>k#i=Q>Q zARUZxQhXv{s3>E63xt3UQ>vJX@NBWPOGkU-sHs#P5Mgb~Y0 zYPSO`MMVs16lMeb+T303zy=bh%@{T@f|)JDL`m30D#EctslYFEjz=0%f{Q+%! z3+@Ekmh;Toe`Qr)ZdzyOqVrj7Y30lV-{^iayMsLx5shBF6Z0SIUhS2GN8rUanOlRUe=W!1rURWkdRp9EM!e`jwf}o@w*Y9shD8g&5NNoY|Oh zms8HG&%w3T>ku%zcnRhEH8?G`g4rexQ(4pKa-d7q{!n~FOIy6(r30J8eKti-#_vL7 zxX9{XA`U(}+3zWS!`#-(ud-UbmYfE(%ZT=FpiRjxZ-FJmg{k?9sizMnI!wzhq0(zQ zd%w-zgV{UYPXEgFHFBF87iqV64eqx;eW6{ITXsrEZzb%K)H>F?&OF6?juS|P#{J( z-!2qR5|`-!A+2Z0eQap9*(Zy?FmP?2i3op|Y2B2|+!$x7;{0tpR;SI6&^!_$LHYmIpNfEf+IaS=F@G7=z8C60nsKu>#{IA9orlIA-K zD(8cjIoi5*ZE*O=(6G=5sHq7Z4bxYB7B^mysg&v2AH7Y)h*1}hUQXq%>bZ@ct_Ht* z$lu4E3cvSYfr^da2I}TRxTV%AI&t_mdbKA6G6s{s&S@DpF6BFStzCTj8v9Y@>I$7A zT`|dBI?zg>=JaJ}kdtVgq99XTJ=~1Hi^&PxMNb1ia03pzu)XqBcS=(n%_M{Qu&Fy9 zhO?TBbtqQY?HWhqLoe}~FU50n9l5KGx2nDoSsY!=$Jh;k)|P-QP8cF6j;G?VJ5y+d-UZ)DO-PK)TdSUB3t~;PC#`6cT zVJJJv354ha`^SxM=mh8!ORb+<4&rKe+8s2zUF=@JJF+Njbz6CI8{d*)5D8<$eVDE0 zJ5lJy`QUcws~pH-X!b~Qv)ODmLDj==%f|d!YfC8)3>zm5^UXeIXY+;BQxUFj#-SF` zeCxVgI*WMQ(%LJ1&;!0ZhFh`^TBJ`|H%vW*jf-Gw(>r$W@<|`zpG=OFkL(cAH`H?oJbza`?Wm#q1 z+}l*$4y$TNJuALJ@e`rcCMNUpGI=?Pyg(pGQN7kcN2U}9CNe<0*`OYH4^T4$TkX=U zxKYrSx#KPd2;$C3#{DL7Z)Uj~xUv4N$rD_VVZQ8Rg$sadOKEh}$~?YX2qlPUcx67{ z_5H3ZLBaY44)VFuTS2T-fHiGZC#$@KTQ7xCL&u?Sxr_=30}1hi#8JA^0) zAIeco#R)uDa6jc^6vZs6r_8dd)BtB;Yio&BjO*2ekd%s%}qw9%nwqUzHk1zaaUuIpO zUus=k*s_1vx(;eM2EqO`nl0jeyfuF}IC)ku9VXrmh3FTA7^UXIh=}8%KVwp$YIf&l zS40<)@^I~HI&=Z$E}&d}94rS)%2NXC?e%xckbAJ{2;KBhHr|G8Z*aKP-6S)vf7|&<39{o45Ii z5R+5#7xAa``_CXbjdX!C9(x2}XsUh&w$l(?wv0pDrCIng1XI+2FL>)$nNP=pRGo?oHEO81pwt)zV`@ednCJv? zLE{3A3yM2xA}Amri84NpVC#ZQ6|Gk5Qf<|WB!Q5w2Up3kr^z=Q3YqYa$TEhp?KFOSvA; zg_Ex(dhwqxmrI4$al)$^yox%lVBPMUz$+YYB!>4$4-KcuU8~!qx)pxiKGE2CT0`_f zGq^a6O@{>xN5$$^_M-<^Z2{q={R1uf#?x}ICteW*;WGEAH04^Yg|pSdVtFPC; zoz~MPxva5wwNrkT`}MTES>C=CCMqC)l?~zxf!HW+C^n>uhzvmtcV9@0DBM5NO0fM& zdQ&*d?y^1x&g?;#;-iLGRhwwB`dS$}e*dsyr(oDl8ItMe|9qDDGes)#e3JLlgxGQq zdVvwijKlgV!m!{-^H zfbZiAc;=l%%L4HxN}FNHUVBBHpAy@+Utg<+H>E77q*;JZkrbA0`(W$8+VYEP#712o+W@ybf)OY%OVp0%C~?$qv%1#uGGtsB407DfJD|n zS+nT3!G)r$sAN~#X)^}IgM_?s<++2&OqS)SZF9ItSsa%(A`Tjz72$b8**%af#O zfQCe+e9TuX)65w)#~ngd>k#v-DBBcem(8=u|ByX=7B~u31q;+UOWebCTsG*{MxD-z zX0VRp<{W3Ak5r7eUUXJWv`^fh_IYQ;TzwYNrA1?#lDZS6ObenG7NH={L3pBxee#4S z=R+#e&HqqHZui`CIoDJ z7O-{XvjFVE0$|S(tD1iez!D>H)b(l^>&F5rRnjTF6VTxDsH%gPVgY;WO+2u33VO;> zC;XD3%LMOk;1LUWdN-9Uokr#GywkzTt>M5?d~&$6jwrWbH)enbEEEuxy=!^T1FWwK zV8O2svL_dBT(iZ}h@_1^HN&%#*Cigyj+r9=28j@R( zuwbbbU)v7WMpPCnx#l|OpZbi{Io*+1pvEJ#KvPp&0~#o z`J2PvZ2o3OS!Vd!I1(FG2IE~P6&-7w$DhkzIe+kdBeoC`;uy)ZvBvfIOro*I5*g7c z{eAwwJxVu8rUyID0OziMXsquXu9<}%UYZPDL?NWB|Jv2-DZG|!X{vlje&L()_hTc) z;oWwImnh)5rT(>Uq6Hkx*IXVSQyme{d2!2}P>03+=_omDJEZ1fHf*~qYI38Nj zhm01NcVdpFhU({2D6bbz-NSsGz&jawhSMZ7NPn#YOH&2@YouH21jpR|5O(_aa$Oa~ zXb$ubt3+8X^=LO%v>U!B?KE3ETDON1|1Mhl->JLIv#K_z>VOoAd10KudD}n%Z>Lx? z=#%g#XqiRAulQ*syy~Bj@Yq(LgyZ=I313m+cxW+|-TQf$MMA?os^RC2MrwF6v3~Gv>@1l^gh9P{KUO#GMPTTDZ zoe%QaS*>40>(2yC=A4w<#@QP8^8{p^0SRpUk>vfU5-Id!B9qQLgFI;)9#4=03jCcS zTwz!RyL)qg{)ZVHoqHi;Jy`#@mIx2m* zy!3wrI~^3>Cs7T?Gocd>-u%v;Eb?V_Se>gvjh*kaqpf>cNe-s#Q;}5Gbxk3U+XCn78K_2@|bb37Yh1U@#lrMtM(Nug;0N$%jPmiW=i`KrxuU+fOF01;G zs@`i=^T}YDFO}~^t3yo;zq8D-@M)wrc+(P|?eJx<9$cfzw*vtiylLS!OSf62lQ~{a zhSq*X`AzLf^rtoQs2ZuE5d)b&589KmF#!7<5&pJsd#D>JI&3JeOddcoO6D<2*>reH z?Yw??nhq0-i-~jn+WwFlichQR?N&8kOqk_VndDTkk?Pk6T7V&~!Iv0qbzmFoK7BE)>PauBT;O!Mk(oAK%;dR8VSc(3e<;Ozw+lA-q#sR1|6 z)l#NwiGY0dYxOd4)h1u?ik&8EDtNO%W9bB%d8_P7<0+9ew106Oa+2RnhMv~aDz(&Z zEt%NuQM~p}er;duTGdxn^(d>FPfyK-CSUAs3-R*AZbHzqq!1qc(1N^Yl1z7C86`vC zq%ilyuC@JlwY{?DzY@Dy5_gZRlg&GlP(4wGr0UR7;3k}db?-~;*5Oq&8Pv-dG$VdL z{whlbN%)fg8(67_+*FYzg#K`Aif1!JxmK7~fN7z8u-&c*p+^wF?gN(;vcboy>mKIS z{cnZPfXjfe86jjua|P};1DBe7=YC#PjO^2$gUq?&$?sJARBERTjzJVMgTr3`px1}_ zxN41A+~Qc&TfIp&|9N-O<{u`P#Itu&bKjciT|pCXk$hmB<%}d~M9!WqM9?sOWFW6j zV9mYhzI~Smz!!s7drQ^6!)oV?K~b$1emfFTB-ll)mVRlJY-kPQR)W~zL(Cl>oBYlP zNQ~s?$cI&=PWS?aN1ebjxf*!;vwU$fQ^h@TVr}$Q8=oGUEl#q61QI0|_e$GvzXM#B zop`>6Z6^V^4*;-iCH*rS&O}MJ0p|&m?bZJrVe;V@MF(hWzafa`3ukLg!qbaSkp5+;ivU7j$xOSt3-lS}iSNtlf2C1LVl3Ug1GSlho; z+uofV+PGIF2lRi#hI^3}i)X`i>YK!fMU`0?q;0s5z%FCMJrA9V*l;(Cd|4e<=Pn^E zmkcfAO|A`R{X0?dad`nZWE7=lZz7g(vzRr zM%5%QlL;xR^XBklq%pwGF$tLtn0^ThiR)qT*fn>#^GQ05wOpI!)r z&B#v!*C=o&8@QAJ8@jIO{P_Ii6f&v#p#90kHY;uj1nG5x=%Cy{zi#s`}o+ z#mHb5mt;-ocZ`2Z)!0&14&f(^H;ihHug+Bi#XTtOQ}ZMcloZqsl| zocVH6QmFPog%dI^826(T1#BoUQui+w{GHT?>cCpw+a~d;pHeU$S}G+k$J_y+*+&AY!k8TulZj0W>c6}rV><|_fb z+(LNegLKOXbX*NZc`*3=PdCqXC#D0Iwb-y2wOvfZ{x}RwfI}wmrN? zZd92+tBkn~l0B3WNg4>Nu%3K1eV4NyGV^@5HlPTuXalhEOw(CL`EW@qHqQyzpVh~f z1>=X?_EcG&eOJq+SL?5;F;5q&#fd_#Hc_h&s)VW1*Q(Sl>gSD{LV$XgQ@$+uW@=P} zZI5XiC>L2nUbl$vUI-^cmq0uy7L7NqVMp6)Wfa6mEp_*~NsmK&e#Yn!RQmo5Zy4~s zFO0O~wZ0eg+h98+A-p2HPhNq*(KcMl*9SUhJkx8!dP*44@i`b9_zYN`b9}APw{qHp zmQ6@aon|@kDL^HzrIG)gU1-&T8gOkLp>8+XU5L);dA7l;zBY9MA`#&DsM>T&-ROvW z>{%%W@&pN|rBS`>0}bzIv;x>+fc5s!7VQ4AVaRK&DH3CwTzphh=6*wx=$hS)K8_IZR=u$(ud+Xk2XBb0LS1}I$T2n5brKC^v(>T=Nfn3T2+muJB_v3PK(nwNmG&5A= zl|58MW7TrAZ3%z|^YY#{F7+l2Vz`h1jqv?wY@Z@;*6@b@7QBg#UekRKN6>jg=rV+f zy}a+=>H99;_pkUaTx%8G&O3aJ$N7UXzQ=h>e&KOGT!rJIaw@x(zwsEHDMIYHV}CWeZ*Mgk zm~Bf5Yo|X;YHQ~->SWrfY2;^OUzA(l4}dix)y_}vTRR7+a6GhDUhieRQ&cWCWv#^W z)*XY@(jpB1E;?&>NX{X?6SY_yuMgDgdwH#VGt!}wq3Q1lQyp5g#>4dx6`4vAaQ)<8 zH062W!`L&1>pA^xat6Pk$@enl;-TJDc6S5UsI!(6XFz1A zTG`233EhRNY;>My){zIzQN1YEtvjk!Kv%Ih?0ry0&Y`cQ!P%{ytK4Us4Wfs4jVdgW z_}=@F>~MVL!iK$D)y1`%45>_J-JP{}rOKs3;;4gUs29z9)Y#-fJwi|~F{Mz8Qfnj< zU+yh3Lm#XyYT@ZVZMx}IAFk>LQeDztn-82o55~g|%l}oQb6!84GmD@02oeD6y+we< z!Xydz{*?~R_EP|<%?-Ssy4d!8)Wwx}{oOC{9BkL+n%gD)J1-3l*^M|*JJ(L{GY zu?Je$)>B(|GzpvgU<|cdCbATeB!_e&eXxBeDx?m%?cRzXsFnm=v$?y#g_w8lUN&xz zPJ!cKRiHqV#lYRY15)qdE6R%H4D?k$G<)^)P#dDPh zD$rX$$XpvwvpsMG-*Y-h0XsKDM0=EJQW;@vXwGd>(Dc++KGUc#3WSC+LxI8Z==2Mt&<_xK* zbB&kqTR*4KK?jZGFH+VJqcioh8)DiGRzH(ZHm=k^NT7BOwi;a;H5n#<0s5`}=~EmnSQvE5saXxIrS5LP zXF$6nd&`--6=FeRljGDvHDXZAHfKBcx_Rnf%VEjT!Z*EP&R@x<7L;q=K$K#$M6y;B zJ19CC@(lY&u?D(dAE>t4Uk4Q9KF+h)h}c|Cf4W|UtGb_{gfGDUSX_V&_iHyxg!xtf zuBsEQYQ7z1cCBSU2L`+$ijsMZWu*a7=4T{zm(w_z$%jhR{r6^a*lxx!Go{{HRTrBw zEwQEd%ol;%yoCrH6Cr=*?<6j<^(5+CxXGl;%^Dj7&|H1QEQdMkD5GfXQN3V#x@9MO zM2gVOV0$}HJu3Y}U5)QW?dm{pn%TSs9jGd3Tnt0w^YjsGU&u#p<9gx#@uW=4DFT0~ zR(DjZ$OuT4KVOZe-G8IHcbd%N*E|@tS%dU%!FcVLSunPhkyC5up_#RNX5%yydOS3O zp>w!8aw&=}aIOF*b=I9QsP&JN2^{COqce>xE{0|24$Gok3jd_qKFM!8&!IxowE~)N zWV4bc<-NLQ0}PjnFf|8nT8suO=ka6KGz^bNl%GpqWh^Yx^fDKTXorgKEq7M8ze<2* zg7|w|n(uxML9jrsP}>qRy77$9nzMAFk_vcU8cnCk)KPm?|}y9zTR%Kh5@ zG_k5XtLm{yt`2?jN~(_pk#sys=(n(#?}@P% z`l|(RB_Md_k<3``_*>fd#@dJ^?EYqrE>p4b#Jg=|NyxY%X{~=S~&`?$f?_$R4*N zRCm)JUfsOurJ0rMudLDpEtqh&;PS?2xWN4haM=I3TymAT(E?I0Ak~4syl)-Eg64R>uq=2NMZvP*J$=ZvcPEcKtk&tO z6{HqN`>Yg+cZYYZtVhO=sCs@j^}J^JKpPr@ zjUv`KtsEz!xfe2L$i$Oepw>W5p>ofa#m{l>#EDXJ-=j3zbSADHPa5NkCB?QBlil*v ztEv)ciy-0e0TYI-Yb-tU&XqnrQ*NoXyV{~@-o;afQ=*$wqTs#(D`AA#XeL-XFYOFjK4*4KVBEROqeUNm zyDrm5pz8uYu%2(-;4{_c+6}fnx*Ow0%6+i?5Bg>s0JMX#`zC%SLp962Ven_-R0g5z z27q^8#B2ZDfT4aFf2LcR*(!4sWla4>oz@b6xo!JpOd~gyCqrANM%iOzt2#$jgH|8mRy(xt zWmQ|~w{l)iE5BE{=~k}L>|=tE+?F;A4-7`IZCieD?y}$S?7>?gO#aeeRLk#= zo-|t@JheY(EfXN?#=!D?msQ`-D8l#K^ol)r{O|70LI#v`2 z(_<*uVZ*#iZ7<$c;8_er*?!kRc0SM3M9GJ_Y|-5hB>>8w@WE?xN{Rc@y;{=bQm z-5)JK&`6ahYRrh5v_lz~wt_VKRRu zzy=hArF^uo%IK0-!u-Ru!%i18NYEl}Yq1;W7#~a-jA1F7*2?IrIUX!cc=G+?rTVTE zrj%jXpDMm#seJ-n?~4>y?jpmI@qkc)Wh|Y1$Jls63Fa6(N6&o67)6@+Y0kpWkY4Uz zkMbR3Z}AHac&G};LzPr^w>%m$B2#^{X1bbm)np%3DAH5H*RNLMbCvjXXV75} zm24lwCpOfC!LSkp!mrg-Mr5W0!Z}MkVE)7~U|$K?9DrGXPy2fVO_0UhNkqP5qrAmj zZE7)xJK)up19KO1%wvhRY$ld;XkuT9LDe$OU%o{la4Rzkto?IBSHpl>zwwA!c=J;6 zWBg`4RcbjOS?egR-j4HWCLRz=I)rf!4O0d1dARm#pi}ij%&T8Ma zQt9^B>UI2PJ*EBid}Oune%jzsP>o}OSi@VZ;S<#`(x8~PgvSvvV6FqmlM2$rIfS#> z->txfx7>T}1+PW(C;KgKrxtZpdAdbg?v3{jr&UArZ@jJdv>4F|wORM1W)2Lcf`3oy zctNUF+lFbgds-HiQyuNEW-s)cEe!K`FmgI0sPasLiZ=sab$>U4{^)T|LA@R4k+VXr z^r00@A{@S~Rtbr5+REoJFIq6vpXV&{(0C${4+v*ouJhpye0{OxZ3*7EuMg71n<*1h__p@;F4Pj^#v~8Kico}c@ zt*m;ERuz@fm8*}^QKssVU=nPb%a3H}H+t_2yI@;;iSWti6g`pkp`k0#*P0~3wzvCu z6)~!PZ7qSvzNFN1)7bN+`P{m5#Z|$XGgI$!*ph?T{U~`PfzQc$5jIsCY@cqi=wtiQ z8Bevr|5>U{zaS;PPCC?V#~0aWu`YRiVYNLO=YMPpx+H(Of_v6gmw_t7IL1vL1!a)k z_+^{v6?Cn+1HMD?na=yoVtqG9L(L>YM7cU|Z%Rt%1!vCQijyA7Bs@k&W^fcgM;&m~ zWiqszxWyvsMAa2hUyGx5jk~5rk4H%1tXLw2Gkvz&c2+i`3sckRUkkl4^>mKWu2Dx>Lz9+VO;!1%c$Zt+E0}^@0^dUM$7ed-_`Dg9*b7^BF7)R3K*yycDf{K6WoP~mv!eubMS^3Ic1?MTc1G-oF0vCn#sVL2YN)FgyV z#1c%f6~+-r9s)mk=XM0!rt+EpOWSd`d$N?heMHAo0M7+-eS&p z^LI0EZ62cI3bX?gjXb8trD7Z}2(`w&{bF^twai;H$xM;7h=cX)B0F)9e&q|GJ= zhL;Iq@fn5^AhO@0l-B5VQEV+4W=#=XK@6Q$+OdL+gu*mJqh!?G$!{=Q79^~)w z#Bp8Cl*E5EMjwH$)A#_!o2;&rp+Eh1)eG3M*Z~Zl;fMAuAUDh#F%ez(4wviWdKFQC zR!i;psJZURFcdH5$lVzyk{Ta1)4iWnF-G|g`Ol{?(;&?COosyYhfyCF3`enC;QsRh zk;#MWMQCTbE5b;`(bG}^)~tZ*91)w}bN$Z;{m;ks*=-@``#bvrFy zo$o$`wH*l4RY%4AS^LTPA_msJ*nJzbookk=#)Lb~bTA9GrER1~@&R^yJkB9z6WF=D1HgQ7B$;r?^4T!vZ*^|^jMVx?xJ``)!Hq5xHjLMOI z!M20tS{YjU;BquY9c6a(HP}9$rYn&K8wOqr*5=@KrH|Jqn61qCE1pGH)D89Z$oc$2 zk1SXCA|7f4v^$4)(r>KMIh_x97Yp7E8j3d<3Q_zv0~PwIlUn2;yfMV9p>>7Ts7cpY zY1XQTT4B$jq&KYJQoQ>G zipg4G46tcAQK+I{x<`2Dv1pxT-2B!UYgyjU>??{aFBd_~n6y5+(QGoRk;-%YiQ|r zi&J*r3ovb#-N#R}`xZR`@9)PP(|J~I(P*>`30{5u7`UZ4JIfDuzT$irWV;d`d_0TH!H%0C zeb<>n?k!tW`CB#E3bNn{vr7CTV^!pDQZWUyOJ@jPDnDH)>cd8iFHOmjktA+)+@e-4 z5r`=U!Zzt#Bjr-)GVJ36Nsr&QX$Y4ILbZ=XuFw}+j6&c;)lL&k&bdfxqk%cyIYcab zqXEln4Q?*Y(@SsE4X1=IaoeKI`x5PcJVhg{u~t1KYk@sDgQ!Uc0b_y@P}ZZs)xv+0 zzh=sBRYD8IO;Y9|)PI}Dyk6D9MsE7w|EwO5lDCKPdgoF zsuxbpk~efl*}qM27rh_Dh*k8Bja*SzkYz?lyc9iVlPR1}7omy`k^guzg5BG!@E(fN zyM*J8nAQg@ndcRPFz;>wV4jv2EjzI2)4_#Li>5!|s<%m27Ad%YWlD**5*(VaQOR9n zYjnNA%A4TwJn+u`!*t0zFB{X&iLcQpRxWpk+z2Oef_-@}eoud1=SXF)amhO`t-Bh9 zlXX74Z0a%{Z`M!e7?-2WDoS*ons+!AmsL17PJ^XI;d9}+Z|lg@d9`KGjPJ+|=zW+E+Hb(K*6kwBpe7sz;jXRqct5LJUxuVAgTCfj z*op~({J9q;gZxqa!q!`_KBO;$cCpIasPb1P=}cj~j*U}9VZ8At)!C$(rG`Jy3a+cK z>i*g44%Z&B-5=@Iqh&Z>X468;uStMxSn{HjRx-4|wYgsPw+VM`r;77!%G44{n!6T) zz@4o-hP!sqtGo3|A>)n2j%3IcjMn6ekyHq_ijgWQ3mTRp2{Cphz`Dn z(ob8u`T@V{!q%zbt|Prh$Ewj{hkF)1t#LD%TX2s~nv0iC{j)p~w~5-gweM+DgR7QY zE3OjTy0b2~)9Ns2U>Sm5BaO^_j~~O#J`zED**m+)`gM)W3)FaIdgF=bS7`Z*=3EfVI>Vqwp2ej*AK=_lvln= zW?ncsd$8D&YeQ5tbt?W_TWK0^2)3=}3*9&w4g)!65S_g+3tk4 zfn1F+srH_Ib-%4wRN>tf=~fr}751b;p=-fM<;i&$$U)_5LB7-av)qULl9t9! zXj2v{XJt@1HiODazrq|U6rz$09ZapPUhk-yzqh8|@@tNsje-D?4vSfK0-UmKB?o*)z(RF9qS`}vGhKT6IhpXmfiht-AC%h%qS6{h7 z-uOoi*I5_tlUt}jxR*?9zA>zyv4U%uxD=(t0VlF?teV@U$m1ak* zh+novlG|&fYJzRbe4r{D>us$YY;Wa(yK}vmFgWu@z10T6;eHcJ+9&2t{$Q~E?|KgEAuo$V6pTs9cb(G8KJeBju~zJ3O~F53=PoMKN2To0ddts`k=o>=j_P2BDDsn z^-AjOEhdbI{)*{t*BfCyY@mb^Kx(QCQ0a?OAgSwsj;+M(LcLEQg+b1zWWCh%~hu1u3@95MF9W|FvLam#I$hOsHf$ELA#m$={ zP|DUZ!L~*+H9*($$d{8>e~*o3`!?2yCWq=;+3r0k3a~tp=na6tZf1wz<_@+WX<`h1 z7EOr9?(Q`md(zmfYU`Jj+wleCX416si*VQQeUYb8VYc^R?R2&45up5pyN&WQ=gWMc zHt-<+6+8`h4N#po^vt`O$Y)MveSYDNIYPZ{mEC9g2H~zjD*gb)!(ILPO6%R4TG*F* zaRXl~-wAgeq#x7yan%5t-*lHXzg2GY-|;luRYJ+c(Tv+f8d>T-T9 z-=NtR$n4djzoQkGTR)x?6bs92lwvl{O0#s^!WF6HvOJr(t#=M_N?e@_jTTX zUsk!nez^#9q~N|z=RO>BGE41nZk$1KX46kbJv8Ake0%reT-Uh(^KaK=z1N12@L}q{ z&f^6<9{2=lEgz%|Xcm{H%k|rX85l?tKzqqAlDV&QH~KmM7R~J3`#NW-B=UekW}Vt? zMu~Suce~!i1DB_uBcRl(e_!XS+ky80@L-AUpI6D!PAZ4z$q(q>Ho;asdjxl@(^wx- z{{Q8^&h&kGLtrA7IC2W2fkyX32v_P*?rBD-(p_1lYE4u0%DlaBW80N^j$3$ZUXu)= zW-W3E7Lc8*{~~tL((1p_2t(;57*#FeXJRV!YPyXt7ojDO;Y(UQ9%#(89^_`5*=*|Z zQ7y${Ro57#4K2T98i}t*QtG$2i6K^CA-RBQ7+PP_TJQFcpn&U=p=TKqHEoyWg`_=? z--RbK-Bp|H)@PYfw=QNz-2+7!n%Y%jn*rQ|hn>y%h$$len#Aru$u9ef%6>~y2Y4I@ z9*w%yW_cYwuQl_J^Nw`qVM3y3uZZ22hgz4s1^;XTtKsOOsiELFi>vCu@nD|0La8|# z5BG|2fgM>ClnDGdNAzI(c)a%tYAOQ|FV#ZyStK@PjXP#n5Alig-Mjx|QC1H>64pn8 zb#bvPzW_II$TNcdjfU2NFx&-e1KO?aBA~Z}q1Q#zQ7)9szjyDCLJ8#n+M`_XbffW; z>3Cq6hxYmu+I9oq=(XU?mTayY{BJMeb5kAqWMNi^66(;U$}ujcT#EHayxFb$bRshr zu>tn3TV%VfPXWI+8~E1(9`b>62TfByT~Bf*){%wL@M{}kl>F>v#|N5kWpI)`;zw*@ ziH?Dh{MN-Z{o+UTct#k)4Q2voCVyExO>YM#}xP&k1dHB$+-b8T%B?imp;aK?xVpYSk=AnOU zWfQ~O2Qo4b*Qo!BM-6jtu45k7Cqq?Cj`Td-Uh{C-jt1Vpv{JM1XA2n8d;M9sEuB}i z?ar+=5zhvftnvA*E30Ig$ka+P5LkJ$WWf(gYtsm4CL+1$-o=&Zlw=D@?3=x~(z`&d z4vkXFwO@%q9jssL&&dUIG$*C^ede|~S;CxTo&-L;MYO?vnLQ^-&X%%j?dQJSFK4Lt z%cd~mT~g#0NsYhtC)j>6IeF>aEOQK z;1r_XJ(%TSIplvn3xn+=J#*xgXR`)lA9ci)&&KA}u-|ErZKWjkJ|Mg3uT=C|6=g)y zw_8Re9-En24QH~Qk$aRitDa-71g;iyCOHJ_nI;u%IluzKhw3>#dH(>Ak29Q0dnu)V(TO5ZDm!XJF@ z9svsC?k;>p$KH6(z5qzwETS*U^`8!hYKHdTWe|Nj3eGD4!|6H&fu}`MaHjYHnmQn;T@rLorIT8 zk>UJ>#c=!_Kf?jpJsZxM>wX@x37wLmM|NcO_jL8*6*;nsEef;vTM6WsA+JP0nlXzn zsvM3$O{{{4m$`j^olc?aZJZF7XnhhG-2}^4XFcWSZBKzd2Ku5sql7vHgdn z=lO2%`tWQh?HMS9MGBTUAPY3{sxxXPd7{&RI#}4#j0FkdZraiAC6+X1gp725G1R;j zcJ~ArG94_N`Vhf~w&Oh#P;Y$U`d9Cm!ECg*6t84UsRcrqAH%gL6cY7&K#LJ>e`G_> z(7=IneYepi$~(fA^n*NS@U#0N(*>n3nx$HE?G2RJtlMa(8`4CAaZA63;*7u~d;ux9 z(E>^&PKh`*zxDum*GKQJf(R1sG5Dk4n77(eF9hmD(D>y3+%xF4;zo@9y#Ie|c*%$`2aeB}phsbPuLkIWn%$<>6l z$dM-Zk3SQhvctUXF$;7AnT+y3i{&pC&K~?=`|oL4$r#zWgTeM|Z9FhMX?dLA^06|U z#~~Y1EwetE(oB03GZ_5G5~5A1%0(R%kh6OVXmEZdmSx@bDcK%u)6p}klDXi}+aROc z4WWzOUicHUU-a>Ql;xsO-bY-^vx!IOne4mg>hs%7$N=IKVY+4NI4s>w%T-X=aHJhz+{o0b(wiqkZ@pEr^Tmfh{+Dv`4V_#`tw>j>GrfVtNaaCNeoZ_d|5xM(?2`) zb3cS(`pNJ0WJmdYnoQIyR5(&RcLOhweaN#3TE5demQ(rJ9L0m6l*Q02Ec=c+m1}eq z&ABMbSmw-)m)?#|<=Pa>vCXmiQ~_0DI0z)Bg$u~AFvov*Nb4n^UH z<(r>!H-8KGTh*u)w$ksmOol3BFg(Fa*BUkb$O^dTAhI9AT@PrmI`Z=2PxsETtVBRD{D`zqlm}-dYRx(`8PG|Ndc4~0m zX9w4<_0C2yPnu7Q0&$eN+2;$!od0p4jNosPAN`>so*gt$#Y$eh~Hz z%AJgIZQ6JfG5P@eIcXD-+*TJg-a z{3t^x9@cG@4={^Z`07;NaLLAL4^oMLy<1!BoW@&e?=jk&cP77GM))GH^@)5e4it)n8&W&I>)q7mm*EO}koo{OI85BE={fHCIV zlr7~Msi&jPXJQqn{?=Iit>PB$iG3Mmq8O~RsnPjLSv+m;nt7Hho**`TVET_{3XNS= zM5sBXE^8s*SQ_*v-&pD`OOZ+D8A~%1HE~5`bz|=Pz8^MYcqq{^9Qj9Pgdq$kMIX_Nj<7^RG z^zf3&R=Rs_={3zd+&3F<^32AwX_4a=5vbhY9dWq9an!7o-B=yvuv$HkcX5BucC4p; ziKAKhtQ&qtVhjti-ub64`1VBWNg&dC7L3b@HKV?QbH6hC(W$>%c*N>AW(>Dz?847r z%%pq1KX#hu4*`_cgKbX%+!njRc3JAOhZMmXIT)7j*5N-0m7{1Z*go4{=bDqP$Q~|Q2X0GB*=}|=8E=W z{t}rgMeN9;$MhoZD4Lt+$YBRWnr=s#);llaP;w6#?dKZbE%SXXl#%%^3r^ zn~AYIo6k9X&gJhx{vMa#%v=s+wlYQS)?g6dT|v!Yd%{}0ln}sDMUa}4p&2xVqDmYT z(V;V~_AB($G)Y`yQk$Z7FY*`$UH*pV)I|P+;1KylzueG6bc|P>7o^UNWS^;r26wB4 zu*s{&vihrJDgp=Wk3gpXTyVgq1Yo~_HBWdnFcsgVOH6>TrV!senpTK!Rz5(Hcye~_0rxuV?VN)!lxeZ^dT z!c*UzL93*Ymx#vGpBKZV^FGI9Ga39vZum)xj2ei*k>69(V=6VMiJ^hgY49|wIiYq0 zSFuvkm>O6;v7lNTcD`XjwI=NR2y3m5Iv=HR6=$Px_MR+aX@v*?O(J5cOY5C)qCBhB zs0~q#a&>5+d2zW$+ZDEM$rrQ z%;JOCwj-`o5@$hj<6e{0n#JtOIy&iTxU(H@=)Ol5ZeB8Z>ST7HJwClCw70JGaK{kZ zk*WRBee5-Q)_~3y&%Iv$hcBgtkkMr*1QamXcs&OrA z!QL#e6U=7M-$fC4L0Ax$YH)rGJMTq?_SA7BLQR{_ZwFg*5!D^!9zMlGs zvAM|tT6Q)P{;&oDCC(`&8y1zf_NMFoHZ1DdfQ!>v+ET*4t8ntQL@)mH&`0@&0fX1}3{RSf@bf~%DPCTz0eD>&v7CC5*hJLAkIpg$udwE|nW@3~223Zi^7DLn zE6bsqJJ{xtS@bDTD+KB~K;`?_3NoEiHd@LrA(3B>O{!P~!!s~7pbV~E2$40f`sL1v zUFEUq4^Pdx2cGh#=M3R720XYQYXU4JLFA9<&pV#8$+nRq4bB&h&Ntm}@PKn*uh6`- zS-yS8^Hyey10>47=^n{1!Ul)ioItXNMseN?_j6GL4U{U~%P+l$l{WXk%5E`9Wqak8 z?dzA_z#c5Jhk#h(p!;@ATA$j^R6H8iuG0uFU2+H}>x z1>3KIMjeZ7@J7%G&}nBX?G&H4MU(J~`a+BQH_ZZVLcy@vO%~{*$7yz<@DkhS&w!}& zg{)DT08!^Yvl3*5&gHlAS|7B}R7yThWq#+lPftP!t|DmO@`xQF=a=E2A<P3H~t)vPYqqi7ocI#!LZ36S0!EqQ2XH*}o zR?cU6Q_2vHXfaI|L*D*?Q4E=~v7J$j-wBdi@@$--Sm!95b0<^`R6tnr)*Y##1P=tS zmfa`P#!AaN<#0=nX*2=EL^5r~R;gthi0mk{_otKSiMNyrj|q>)(v^LC0{lFET|df4 zoWPmuDdO3;YYkFcg`~9(2w;{>GoVjaH1TQnEygYTm4qLXtgT|4J-=+NXX*Z+=i~Hz zJkJRutghE0YtquF^IgQbsiK*uDl%S0CfW~~zw$jXA@w_nE3K;R5;24&R4GI&ny6N- zNNIuJA`HjYvoPUz=Gp%vMdu&m?HgkYX^{G20A+TSXebvzBQE9a!Uf2zQi7DYYq zfZ)YXgtBbHd)K#)$q)0a<6&jYH?xk{r;Mpw>lpV~b>InD$Gh-_$#jc&C4Q5?H1*c2 zDLZ*(+D`7Qn5LN)d&J7Q&wQP>mPPjMz&*TRB4`^^bRSYm+2Tes**l;fY(GR(M4aQ3r9)2JUL%rH&KHPN?d){f)vViWtDC; zKf4K@cV{4Y*zgqSH5;rDJftSmT-CpcZrFYjIyfYQQG+l#Ssiprf5zNMOhoUL*d*~+ z=#@56N^i0z)|+^X1umx*0vLBIWP(R;uq{Ka{Whk7cK!ycF&x$YDb{{yKmA04mUq9$ zASOdkisgB2iO@v5m$^rMDfTPf*KdgM<|E*G{moEMw}OTjJPEEQa3Op5pDe+$RQ7A) zN^qXcm$Vq2s!?@H*9uFH2=&Gn^kRWe4UN!UlCD@L`tkrY{WZ*6gO*Uu}H|)L+33>!bcRP#4z!Qjpmxy%>uh z|E|;jY`&zie(3^X?SjHy2F-+j6tp6-K~oe{viJqE&0-Yn3$^klYcT1n&d4-3U!!^_ zZDCJn_&hqVOCU&=xgV_)#z?*|TK`71eKXbOsoF?GQ8xyb&Xp924fIvo*CJ2_*u5eL z4j{cy+Mvb!?Dq0pN^cPhsbleM7FvIPs$(Mr(MuTmgV(V(1E#=?I)<$Z&U4R2?|QOX z9gF=gO~*yT@QD%?x=dr7)3L2`J9b>A+5%OZOf_#!{JK(7$}Qz;T)BJP?jCl&#@Z!Q z?Il$krE2+FP>UF2g6vdGWxLc`#{Eh+KEmupiIbOqn?`?y0QLr8>zV$I9VnASFDt49 zCyfIwk8^E^1!`&r)ZYc_8Oy^Y5emz#55&+R45srH=?H!#qu+ zl@f7?T4gk5>y-?Lj=#7lhrXrw2pl@tcgSqt@rB9h5G{jS_evU1hTb_xeKsTW=N(^K zf!!!z8N=(kU&K!J{T8g(LN8t@BWf;HSZt+=@17}st6zMiXyJq|K3Byr$t}K5ruaC& zc#~JWBDZ*Drub05c(Yghp0O&veQxo?GR3#{iz6U~%)OVY_$Lf;7Vh<#;_u*e zR9DA&#d{g>KaHZ6fPGEUb#sb6dseS zBage4Tlx=8Y^U@U{CB=CyNa*2JR2)5gck9)f}O}uTb_-+h%bs(oWPf~hTcmY4>+)oIs&Scn-lsklH?&OfBVT>C6FifL>ebxq>D4Cd z{me|S{?3E^UdegKoMq9T*vy=5IWK3<_LFaQCm;AVK4}L*uViRD3rQKDY#Uy1xBsrM zXqjH9-Eeviv{Y{0o2RFTP57@R@v`Gv!~dQP{>l-^SD?NH^R(5srmg>(`uAn(TPBxQ zbaqzv^>B)B8|+Mz7iOyb$*axe=Q{PH9E1Au6* z)i>SaY6Rf|$pP%8M6X8YQ@M-Q3p1ko7L@dZoAReBqA9o1V0{*M^J-}np{m@0g$V#T z4qvUY<-4-f-RmpXik|qV#?*t;^ylS@!asEyC-8_7h-&}8*{{56j7YL6Qn+9Fz0u|k z^`h+$G8$62wVuofwmmEK@r62}_nNcHP4mk|B-x^=uznvp$1s14T?q}+(fC@6#$SNZ z5f7a-g8j;0bCej9W$XF94#a}ES51(CoZhee2LX=<4kBcby5OlaQYrnGYWuIRLn#A+Z zyjCSkccpT8-VgNE?LO4}qI>+W>{k{);5Fy`wiClA5|`)1HZN)UYpA~fVcY0zs{Eqz z9g(&$@cie~gg@s~X1Uw`dJUf5AH{JCDn;oNu@X5Hpt|aw-}LHH8@y>rCD(mbT~AH_ z>XWLb(fY3IzE*K#i}Gamr>L{3J$Xf$52;F!>{y&UDWMp-T98UkC%WRgTx~{-Man(D z-YytTjapav`P2V871TX(C;9n9J6P-L6P$!flt*zZ962gTTh;BKjj1+Mu@je zs!Ca`U!{^*ecu&Il@*xV_Ay!!Qv|~3)S^@rF+u-UxKAT$c|ni@Z-83AD%1MOYJCIP z7jg5I{)07@uj-|jZP|LIp3yOX*?K-dyRS3uF1;AzDscs=n`iR{G4Jhj849`8b0=`C zfirEt{3>btL4yp~7cE?GSl>feH%%4+JXPN4(`Sq@tO3Jh=tWI%+TO163;*S5dRZ>? zA;K~5sh_qaeFP9QlZ2TL zl;xfTjXg;8u6#!>mR0W5cQl^Zb?>x3O|7MwT34u6J+%tBmOP$(i`>iZg>17N9IEHjYpUSC1nCN_1oZrPb=aI;zhv=Y_HVtOfx2)19?Z|g$4R9@{Q33B0ioA{jc_xGNpz zI8-&ZU7gZZAOQ7>yv z40gIfG#dR{L7rIu55#g>k<3uVB&N@j6g3`UEZY|bW54H3c)?r{LsSS$`Z#kMq|B4& zn=yrux*SGB%KSD_$BvW8FY&Rz9?5yp9b~CG@M8Q!6WV=$-w-`Z1C zM~P31*;DZovh1WLIB+xeRQ#l@a)bSHMeV6~P{EtCr#{=zi}PPNM%C=8Eh^!*dyQqX z?5X1gobzAgr)8Iy%v_A1(&hT?+fx&10$b=MzevWO+KqnB|52lsYfsHmNzQ*c(d?zV>#Es;KYQyO&_cexFbA%W^BtHPwh8G7xbVB|hXA zQn(fin7rv&;}Vs#qbs%E>ZJ`-2oXNTb~g&P^P2mox1akra={r*$paKn&H#+=m0I!rm&a9y_)HEl~UgD26-l z6n0RzdnK_DB_R)d1`CAP(^$s6cSSOk#DNAS7NnGKhrA`>&WAN*uP9!i1#)=7RO98) zbYuydh4CmzNWDdXJo93kaOY#HUk4~Z#q&W3*?I`EwWzZpU;c-k5#=0&JU@xT+pws% z^?YYh#jc0-ZaqG{Kq@eS+6^@wE9eEeoqOwXUi3O(j@RGt#?L9774H0t(0K}ZH0{G( zftoDqG40!ux?tURjm|}wIXF3@F*bq`UpSr)YUl&M*0bTjn& zSv50)W-?~tF~#eRqh5wu3sg^6x8x^i`P4g)&ajhnGt?UfjvMQoh2dvJ!9{M*@Qk&! zEyv8)m?g$Syj^T)3W&E(IOGv;DduA`v`|sE(W{ABxmW25Btpcc8k_N^KDf6 z&iJ+`Lsr%!9ISgq(VHH7E(%w_dHH~Prq7mj@hc`KcE%cN#qDI}OWD@pk-k1y_iZED z@9c7Fn6YqsC_k{V*9-H-mkR3r_p${WCRYqjhPH*X zBzLqo0-t}dy{DPjmb2Hb6w{QJPl+$4_1nxfW$C?2hN;i^2hd1jg5OBEa|O*>1L>y9 z*;i^j<#wOULa}h9N)KbjWm1f-o1XRc(K)_tdYcSO-!{bxx{jZTvq0onbh!CuBYZ*7 zc$wsmF-Pe-oc0<8!HNZL0ai3tb&RcP@y!wvOYD;j9ikZ^$+VNLUYEHmSE)~>k9n0X zf9)q*dzrPoUaJlAJ_1Vsm%@mc`aFJ`w|KXaK1M(1OB$nZM|kY&1Wp33ztp(TmKs%4 z43h6HCb#{5ahoveWz8;g4>OD~T3JJV#o+iJ)AlIkV)e5q%Zcfo?`sYyO%;8_InN~2 zU!X?WROx#tDf6+){A7Gmy3&?H)~WCDS=bWlxA=C|DQ{iee+EBoGZOST3CX3r(wY%w z4!zmv45x|RtzV|Ru+9Tl8cZ{D9{?t1ZmmIlr)3XYM}@99PD8?7hj?ONXf&x?6Yl&B zv=Zl$_o{KD`BE{>kZ|XxdVZWV=}^vo6{DdxhiEDFr2n!ipE=3EV=wg!%2&fbd&VnN z!`uNkTN*{fo!!8s7qukgb(D&`H4Czt^e4Jx6oc9i8~g9iq_`&~if#GP{agQq)Ou=7 zQmC9+jm!AR4h;Kace*!r49zBg_`cN8>}ajj_G=&kNcIa7^#jQIyQ4Lb>N+l!0~$ED zEk%fy-L(w{n^U$3td8W(%9yu(*b=40LGPwp%1u{(i??xcV_ke$PkF^NSwN%7@0{|L z+hNqURT50o^B^#r0%OVWVZ&DLCS3K}hAY^<5ytW(h2GMrIuNr~8#r>e2&`+En?tItd+3Qm^RJL6IrDXU~UfCS?c4~t^f*lc2aNYx(+KWAnLJ|rO zH8!f$7-+SYi#EvGG=7Kt$VkUs8;$jqHKTAA)Fg&HQ0Z$~}>;CyQU>p?ghn5p3CN zxQN+$ZMbu?7;Zd8hViIj=rJX&{Sk=C&~Vl8%*Fk@l2cW3nCz8%4dH$caRjh zE=A86UxIe?jqwxq6mW8q3rXWlp*fD5OUcw!qI^W21uu{IZ~LnDo!*wu>Cdkf?!Qq+ zarm^~kW`%CdV}**;t}us*`oV3we*QN0rxqeda1|Lc!I5QRf80^T>GEYYfxShBi9B` zTF97uSI06q+2FWQ=i8{${jcCua*!KhN3(15vblUd*bqB@TGTnajL*kedIsBc$_N1` zvCp278SWOk_E`z>H;dJrVdV|6BWLSiP6_yt2^L&B6;0amX_~^1;nz)_W7`N?FB~ZZ zVR!AqoDD}w<55W(FW7dN09#zB{phT6R%nSj?_v^7(=Zr5g2_cnZ%`>FJVZ+aR(zmX0waTDl5%iRHvd-MCgGo%MQ zBfH;KvkJa)zzY$<@tWh~?C@is2Blo22l>fUPx;*@^FZ!^6S&*ep073-rG151Jn(z@ z?6ce`?fUJzQO=d!5)WPN7ss#k^>sa49=bsWql$fds={}3Wau5$^#}EjF+b(+So~l3JJ>MM__WG#M*_TG;O@BcWF}4e zfFZN34>;3bFl>qAUem>QuWvlnUoc!$>n|9_@+G}sSjqrMd^>?(3Z|DQ`LUeKv8qn0 zrrql-7+N%vvV_QIpy)Dpo9Cq6yafYGvebg%gj!KRc9*9&uQ(N^+;VZ1tF&?qu~)Ex=93{Ox8N-*xV06;)8~ZRhHG`o(J;e{`C0Zq z+@r!kp9&#Kn(~g_t*dtn)B-p%O!M@?nKU1$`7f*GM zQRo~M%>Fq@li8}%JwZS7baOtcTrN^zh~CKyzAhnmxsZDs2{C+t=)XvXMw(M1jl(Dr0+ok8MSA@MOzK|l4h5_~f2 zf$j>=&-vEbV66cOcb>u66gAMHbu`wx8S_d;+CVn;>$;KhV&s*aD?;`9TXmO8=n9F7 zSnC4_5P4LCZFfuBQohiudiJ`W@~STQh1gM-he%XX%L%O;0}$M?XBV$H$g6mbS23Jb z@zh4I;vgyp+v?35n&-=1Pd*{7Hdy6g+wPR{?8G-w;=Y}@-%etNMh@X>yjx3(au%=; zxEpY;%Tg$3@`yn$8VjlSG*Z6?sk>L=QuFRmD*aflNYA4*5-Du{n;nH)MjV&$(>zK^ zM3#A!Ht;1aj)xjQmfmiFkjmy!>Me;Lt6C8iB;S97N9j{o(!?>hWdUKCJNa2LSLtZK zvfMat*(*~JBk&U$MuVEOG3x&dekRVK-U_Bj;#e%v=lO!y4c8xr-UCF!%_CwtK!F|x z+&nKo9wW5+zprR5Yh8{^=#?0l42?*kHCWy^Au!9% z6qtm8xpi}3B*^LY0eFi1G3(7&b5C`sXN;NWo~n6-pWV~Vd?=k)2azxu2Rz0X-GGhh z0v6MSg`$6f4~`W)BhZuj8mqa`pe5y+!sH0Of4C&k5?fsDLp9i{D%|-M$R@Z5zDx{2 z(_2^KYxqJB>j<>C_jH)tkbLO$pYNBSghymod+uR`*Sh@D3tNYWJO2q3i1N2HbRN%4 zZ#ccvP@t+7&QjHy|Ft=*Tk}X_()8#aEOlStj?tpa*It$wpL-0iKfWIhO^=QZvb?v0 zKqTC`!A9p>quUxE9XsGQg;9644G_CRa8e<9V?$(v2fi8tMDHwz|8TcjfUe_yHK?rE z|Wulc6JXu+9*%y8^LLH1U$fn`y!f z!SXdD?k3-pv#fH1d(T2fFpuPr?(1eDv7aH)#nfST6pW;ZSZqTB)HBDf`fuv`Q=>%6 zt7r!q;J-VZz6INFFmBKHrcFZT&cd07$FM%>6E5XUoAMP@+bBm4o;1=@UP|=l2C!n@ zG+QsWzs`}J^r+l=w7vCcotULakGfZYjcsQ5uIm3V_a<;s70LcD0tF~jR=bqqg0u>X zIw%a&3btq$&{(bAf+B*7ii(QMC~CLj!lHBw<*^iJ9G7uJ#|0JljiG@?MF9~|RK#Tz z_iEb(9S3ov-uD-IPHkOy@BHt5|M%uIEp^VxjEszojEIbkjLe7&Qu7Y@SR2LjcC^Zm zQdx!zuAkO4Y4%JVrE9q{V?r145f(e-mWOz?)^7dy-Ue6POI=U^*EzS`OH7ItscAOz z9M1h5&gWROJ*?S&o4~nnxD7R%QlkN)uaSnM^b4;kLQ;XYgBC(sO9J9M zmY57&aiz_@UEvQ;6a_xA!Vhn%aNL`!x z>NvNWYMEi9uJy}xU{{+!@|I!bgWHH{sf`wxCs!N$#ND(S$F4nC4Fb1cJW*m0X}XA+ zQp}-TbdogM4EE~o$CbtE58tJCg=lBg@n}L0L=mm#(RhO0X(b@gF13!h>$clfa!2iL zv2g=={W9ZPv>j?pYmH}7v#q#0>^D4LAr!E0(HvKzNpad@`8wv=AtR-ca3_prcVBBA z3)0ly=JGJ*`5TY!4s*U@5jTrLxuX`|_jQ3MuUMqzG#;?rq!G^Fl^0=g#g|j8kbpKD~?Af9bMH&%@=cWt?e!K?K`<1B4$Y#Q^^EC{T~F_oLsXG z&M7z5FE>o)SSCVRdCe@9O0sO#A^`oSldD1?(EG60;GIVmb#m32>drd3;<-+)$Cd>V zKL?<(R~gZd?mpf*xyDKQjFFRTl$>02Cp-(K-YiDo_ig-k{;i7U7u~BqLMIt|{xJT@ zacw=QX9%K*>(8VFlhOPAB3akguYjAo9_i@2w#NCctv{)x7hcUUQ~iEb2b3a&PSuxW z=;#1?zH94Y!P}Z{;iCHXSd|Q4O6Ay`o@m?D#bJprn&GCHlAf8?V2Y(L5l1>;Xm;fA+!-zVGmLVwm~;M%gACA$gyS?0&WpXHocQZ!~L zGM|)8n+Y`{s+Ml+zEGd8STu!y3O!lQpDYWyM9CpaC8+b}nT3XjPsJfY@(QJ{9;*vP z(yXqv_PUih_Wsg_c zu~ybZ4oW22cRv+;I=|pp6_l+hpd!BFoV@6MeN{G*U-nNb8}Z9Jy`Zu?9iXx&0d^&fiV3rHbxbNlko0s|vNmHUg-{7F z#y%j-72G2U@^YFSbv#BhdrYo6-^4zaBAvz*)sT7HGMPTef;Ay*29)J{$n1+Z%d~Ih zO)9c?R&cUf0dv*fXV9l{AF($kM=LMf$+ijP4^e*`qB}H1=H~E1$7v9fBkd>x()FY+ zS`Z%+_b$d_SjoCr`SSeR&M;S$WUj_sL^3e9TjET8NUQ6QgXou*Em>VsJGD9>JI4{A z^Ebo@HaZMu3xg&ML0btPm~#$$UmKO!f`OEvP9t@yaeyYnvHgA9V0G%?P6*ER`QwtK z??>y<=u1I7ZLr(r1d;z=$s_dD|DE$n-S&3kp!IpBUVBMaaRf&DQX4c-FkeNWva{!v zdi_49+^c@MqVctZSY`;K({wD1(X{GkDSF|pg~Znm#3jni*<$Wb8iKoRlIO(N{!75Q zUxq!ITt38|clJ*2_L456gD(Qu91~j_pE>#DVv}X@}Nrtuy zpyzAP^8~LWY6pe*f26obg3-BF#E#5|5wL&lO-PnwCzV}|3VA_Mx#>-$P4x2y~`VZa;ZO8MU zxc*bB{gL3r&~tl27P5&siLl0$#)1Kwr}O*J_vWulG!X(heCystMd{@N;zTKqz8(!k zZ22(y3dU;7O_U#%LdK@kVNCCRZ-w_#1@Dm{5DmoiBRZcFoqH$`3GDrpiYH3rF752FZ8ip~)LG<0S0gG5%he+W7$~0EmkZ z?oYk)g565Pa#{LDk-c2tICeAwvIs;@@&(g-C^Xc`tRta-8j;9VFy2 zWUt#LM}U!3B09o~Ela)mu!|h;TJcls_baBSp5yagVlbMN+^1 z2-Sa!`u_7kJul|jcdmoLXiR`2x?n^P`fLjVkU7MVIYX7N7BYC>LY*aJ*CHP@%7+Yv zi(IKQRceM(8WnhUDs}U~k5DunEfqoYfuEyly$pEx3S6^32i!Qs_g0=z?l{2rRvy7) zv$IXYTQHScCWFOh{K$GMU*AKGY=8^;7(C;GA;80188K+-TB2A<@-bHa6k_n$&)_`R zWz>Tq5<8j&)MG5W(|*^+3&*F49LN7F7Sq&3>9r6t_DbrL`@}aJV2!$m!KGKW+PSJW zNdf1cML0q9J^xUY=xcX(D9al3+pJUNsL1Js-tNw4UjbvkUd*LU>uU$2iKT$WfdsAl zH%9mh*!pHBuKJdmfx}Ic58Bst%Q|IRw()7eF5ere!->;#6QGWR;628&!R_NR6bOZX&a3xWSFM}D)7(b0pu$-1 zFQUR}YSs(AE+YA}5i`Wi#zTH#58T9R^GdeK2$h$E)))J&f2}>UVqRlS;>j_B>Es#Ms59souy0AC~~u8o@dZSglqr1&pQXiKKWMbO?)&)N4Zs z()D6UBlUxMFkL%DpD`{<{mos?*e9x(u@3WJ{hpUtg9V!zP8x}6VP0GbGuJX8u{8Gh znrbW(hOqwcypg?vcVw7Yg0GG?k^1R5pBQ6TQDmzY z7h+~QrA{_r3N$1`XKEXErG2tQ1aGY!+CBnT=8x@aD<|P>4VO67cFjj^YoWFUj?4+6 z)Cz23a2uM%?PH(B4+~t9STkZ?wy5zYl~#F^dg`?GPSxIJ^!_qt+fKHR-ccrlEkLs( zxY}#cLZde!$}Sze;)HNwrEYKM7W@ka+C(Z9<{h9!ZE0WvNN$b1pS}&U68oscCm=(A z`r$M1B~ldeVW!m4ERQubE^=l-C68uGJ=N7oq^=L~BePX|ttetj^h=iYzC>E8Xtua{xql^Cf%(B6f%+eL#vlBFmTX}w9LYHzaLK8Qp*)G4x# zYOz2fxm&O#vCBid(vXh7hSmzz*t^j2BCM=0Zg?a0l2fM62@>FuIva>T1} z?3&7CCC(EZ&XAR7E|z%FXJ6ujmcT-{53Q> zDK`H}nrk_i;ogPL2Bv#uAn^{uhW8~N0o4UdNII*<-F#%IaMjw;g{(S@6~(eLweIi6 z72vK#<4Ljk&(Yq3ArfZ`eXF3yJu$I%k+UX6_u;g2QYstiWTOT`He(|X{V(amK#_e; zATa-R5Qq(#c(X5QcLom|1WDQn;8|3b3DZ6%F|brKUczoBqGR(1h@72$CH@GC7rC>j zLIl_LRWdxqmJu}1i4ntKFp2={C?1n}uL;HjtRc@CzbaDQz83*e9&QVXPhgzyE#%m* zb_a*`)~2HJ7%4TkJTOJ^*A8TfeJplKlhQDi8haOs=vPiA8CiLQl}!eqt;tT>N$Je7 z4t7xFdOC^glWdn{I4QrCI%kZ|aeF@z2f4kdVp?De+?!+AYZ-k!WnD(%D(^hD!Ck6- zrK!K!q{Dzq*rSn=J<3AlunD>0M$Zt7d&VJ4q`uiozNjP#yII8jHZJ1+Q%xyva;cT9 zVreQ1tU`o~9xkXjobr8|Bd~3c-PWH)@@aM##u^mg`(FQNflRM}O(WOtCAxUg(p_^Z z{A)XP(JaobY>7Ntk>aM|8xFS)Wl# zGQ5(Su{nn^(K$DI+_!Dz-u$EJZ>0BJ067`$?Y`;Nskr(EAjlpf}?IHIDT{8?Ogd^ME3PSr?(Z2X?ANsOiciyDMqE z%OJl|<1r=>oQboS;2mXTpTU%3*+A$yrkYkG{3oveu;8nklIsMWx3!q`9?OQ$n!;!D zk_E#|A&${dwwDjn3q80EI4PEO5LbP6kx*mz;8HTxz3CTG&?X(e* z5q@|!-%R!So212BWHoaEmExK_S500o&sD)t;TF^u<*;dM00jU zx7|h_k+qJ4J#<`UC%SxdKq2{<{De`@Zv_-Lr%M(bWq_s&P*i}*yEgK;d zcv9>DcaF1Vf9o(38~_Z2CM&?}rW7ln1vFM|bg%72;#S*T7nB6_blJMFp(evJmELC< z!?DN>i+FJ`M8%@V)eVJ@rGmM-W1U~A`yK3(j&`5|ZczC)r(dF#gU9X^*32N+HhHS}0KKLk$4gE*2~FYHn(49){>5ZkK!$gs zMH@Ujr@%%HSshktMBDzImuUe#5(52?zW)>&wP6|Gf!3$2wk41`)y4lK=9((~uH za+y5_9e*HFwBr}hv{N9F`kMra@dy3<@rO9U_zyUi3c2IY!NCqx2*zKo%D_g_GC_CI z7^}ml8vlkb@`hs{v|kafe2-9%j9lZYYwJnqec{@lJA#pA?v7w&*>Bwu-0)WkGP!yS z?g;*Y8-eHCqPdMq-cTb)58KTrtC<4c%?>a|R4~9N_*`gaj5#p~e9=5J3yI0iLC`7I z>!Lz|fM62}CJ#~-&zcBm=)`ThGQ;Ant@6qlsJmBZN|nEnn!+ZDXv5eyD6xf1%~1=E zHTJ;!7@NOuITEVv<`}_8^D;Jn5fY0oHeZSV%YXHp|LVN#t0w=|XuTS46(9FsRb^j2 z>c84wua2=&pZc$M&%XNDeBngi;!xQeU9pR9X=fYdqhQf(xI8!E zpLRzxIDhtj?5tSguCMpx9XiS1hWUWU=KeMk;R`$SyNCVmdIrBU3-QB@qc@ zi1{Z`DlEkBFnDAXdr5Ocq2q5!Z+M}v*k3}pRC-@S8txt@)fP7_23HT4aocbgWw&6t zKn&)kmOY58uK|#IL?vcRZv<4ObP4MzjCp4HhnmL?%WO94aA$JFtazewR!uU-GCbrN z?plaH=GGO7$~lK6+b^eh8%x7}!pzj?*UA#G<20u%IL-#+FpcUoyj#Ol?i z%|^dSe-#<)JI9{7#_3nrVZ!JdIw%R4akPVI#mgwpN+VLQ_BA~s4KL^yrip^gENsZld9J+lA8D1nRuY5J=?V3z)6DKUB$N&B7 zj(w7p`29Uf{jEin=PhXh{UOBf6|TuDyaA!jFQig_`l4z1c8mP+GYsN5`m>JnZ&#|wD{y6~#4E~GehNmb(Lm0c{K#mdy5vx68k zdAgc>5j|cgh)k|y1d4$i+2wLZu;+T6Wv+}N32>iISYnfi z#92gWj~2O^&O1$1*Nr9Zw|%hGR8F0(h|Rx(!V(b6(UFCSnMYhMdJL;Eb!?#Pd$2sfY24+!Kkl3Zt_lCmB^(3C2> zU8y%^OeA{k%bRRu90y~{n71aM&lj@zC|*g}RIzoWg~yHJ1F(Jvk*Y{+O2^Q+VnIA= zf6!H1T3GKzM@s0HPEs<@L_v9aa?){Fgxz58L-iQm57TZPE1A$>2ECe@EPWzor*b8l zjztGQHpH_N8Tag3TXLM1N^S4C$tcAlo?LK(jnXWQlH4gY@H-lCAIbYnwxC!^%v%_w z;D|K1^fh>MEI84|ah00?TFrZ*8z71JPV81w zr+23&TyYo8Py6CAG1We6uQ$W!2v2+CyHRI&p?A5&2A~v`XB^M`0}}FtxYa zR|CSV)_Uc1p>xG?&_YKEeYVKN1 zF2md0Dh@)=zp(TONhnAdf|beJqA5VaDU_<0iapaX#ju9wfx5 z!d>Xql*-F?FDF9qvJIoC;*_%|04jznx#BT6+s4C99j<`B@_QI{&nh9vKQeM@6^cx8 z|KC~;iwgcr?`se)^*X)kd%|#YlCdJsi`LG*4(#cM!5diWkIX>aY33P2SNyV>Ms$r2 zWP1a$zx{WFUFBWths8us#m9xNauI_sv5n|p2#Z@qo%Avmp`S@!1%>YN3n^SMQol#0 z&~t5a3SI6Oa>oFk(xfs-U$)IDG}13LN~&h83N*YsX@8s&2b(R(1(<ls0{=i zF2B_|<>nrK5Oel);Q(W@xWxQ}hzdG~RgY!@0irZDi2`=~9Tj#8jnc%szmp{q9xZ&5 z(U5j_9JZgUS6(5(z;xUXC) z?j@+TWp_>nazM_xyH76w_Pv@b~ob#bf0zs2TscUa_x=iP9W zhu_{v`@HKXcZ^6ux!cnSTz*%uFxRPpc;_XZUsfREQu0;-L${PUanP{pl9C0d(5+Zg zy+&@|t=qJT)DLycuq7@c-&88^?wd--mGI6tl}Ji=IFELO_#J4-{kvY**F?-9P2N~2 zsWmmYlp+}BV{rMV(id9wB+5D)IR9ibmQrW23=^&4D`TN$sk^60P6C0jPg|6~VIM*t zsoNY6HH~E_eGt%ueNDo!P^vQWEz0^U4OTyy;A?~#8KGCEZozLUrKLS2qMib!C5^Qj z5UFDuq_o!cO=}m4P2;lh#OEy-YoxkOq}tztLi0oBH7zSxjBBl5QLuEZmQOjls+~xX zm!2~!SLSv;=xYUf7BQ>o=;zwgFdOG|YxN0zN?JH;^j6Fb?H@qcVKNh0pB7R5_X>ie zy&V%MS#X9yS|CV+3{vQpU;l@M945cXZxFJizJQQ>5=-bK@`@1o%ABW#gbdG+D+oIF z^jYvRmY`;>Pum(2W>~Q61RjkAJN`mQ3M@Eafk5?H@FcBi z6J7fmxa=wR=}aDD!R^gszB1Kqk`KXl0f~U!Xin?f;q(H<5Fi& zb~tM4xV^=)h20_ZI2-RTMCPjqwxp$FX(`h1kjBa7O1Lan7Us1-A5ux)KQY(X49{OHU` zri6efF4XVe1_61<2V${kW)#y8G^y4SZ(yvm=zXONK`#sSX2Zs+^{ZnW2(V1@6DVe;CLYl+UwUnF#0-?;o0trC~h%F&iE^JpBfb z#?yU&bUaBQ>k2GBf6$IEm{biKjAWqJB3Cra?PibzPe!!Ik~ z>DTN-$b-h>=^FX_Efk3@-cwn9ep0)q&(I1z$V{kBbM*BzskNtZ^oYmcp2vJx!NYWB*VWnjI^G(Rx%kuy6N!A9QHjui%>5i^m`Bzg^FbBgO1I2fub?+ z{y(U1wr&*zcguq5D==T+4HX#HpJPat^_kJm7+4NKC@rr|+zVYSRxk$slYY4f4=P=* z0FPyix=bO<6PP`s%@gu^q#9fLiOdWmX?cq)7NUqv1-P! zT&&y8Z)BtjouERx=zyam2y1DNF)b`!n+s=Q6}-)Qu@v7+-5-Tkb@^o_k>pg>FAu%X zIMrcC4C->2*ItoJRq4eoJ9E+d&t3e72uR1$Z%R$n?`fDR^CXD(E4JkpdNHgS&jjrs z-aEvMKaWw|T*ehz%sGv_{)B1dd=y^zBJDoH_Zu}&Fh+_JdMQyFj?j^YDWZrMzC-+# zjP7avDeN3f*|Yym@*4tH${sXe;c~;o7b7qEW95aq2M8v@39XP4UC)xKhDl|)U3O1L zFJRD2EAC((^A)MhFZSCd1knIeSAsJoQQHufahird@xFTEE3k_Jfy*N{jl|4lAiX6LFpzkR&d3B4=-A?Cdw`77BZ3vV;rsM9uo#~o_xyBNa1JoGQx z)<&#$U!Ujs-R}^BI&u_xfR4E%M`r0SNk=DB)_b*KRb+Yx8j92>&8iRe3y|&~F2m1l z%-CLoo}p^je`BNuRBgtm3IF``@84p^gFvHz8MhLZlF`3)5LF#BzE3G*#)l19_z{}V z=(PSmKXd<)y*71rgS^*?uBXXp&SAz+1zS|T-Q1=tQkU2I?L)DIbEQ5floaNVOA8s} z_6LW!kYmm#bx_`8e`kc>I+*G6Bol6B>N4EmMRy80jMlP^HrU}_d=}NB z1rw=9Gq+-Ptw^xajNfy2V&I^M)IrDMkMYw6W19M(9gGP)27@u$tk(fuztv!{DO8lj zA6@4Y0|NPypl zrGIh;W0VF?gTaCcKr2(V{G26<8LS6L#z(uq^V83iD}u zKl;k!Kw7Ii-BjaXZB5CKt=LWE2?DrsgZG@qC5UrA4M%rfn^cXlhZJw5{yt^_S~gPu zI6~8mxJbi&`UwOq00p&4X?NCSDG%*KbM8o*Pf}na%eNtNK$ZYz&3CS<#!Qj)%@Uwbb7(Lrt;^Y zjft0QIRi7NAHkpg>j&LyQ@yZIq~1J|sD?;`b7}?Zp?M@Eh&6rSgV`z8^tu1DB-ZpZ zKU+F+5~}Gdel0kU7HQ@+h04K}cek9((+fOd`fnKQrK~`#X@zPv@M#vG7W~Q3oXNZ9 zvoSp2NWNUFFXz~oKkLhpd|7a|JvZ>I06?$oOtoVum+{%Sl9(5g`0T+W->U>fm8_Ss zrm3!GbCl2N=subV%x!LSkDm06=E;({w{>dvN;&vy%hJ)07}i$A#wpxW!_ZGBArzVE zJjdyd%_|r&8hwMuP~4hf`Lmt^~_Qc00$;HzD%MP z@q5qn{oYUgw%^-%uQwH5>b&BcaD2;~o!|YOv+$S$zTe!d=_z;L-LHZ36^rE4i;d1W zz+L{E(%c({uK02WV}pp_a3(aD-><&=6dSDpd$iy|q|2dy^P`G{=85BHRD0iX>iOmx z?{of{S>t`fKeNbUGewr}u()>^GKL)z-ncB!KN#@mWNwzaXww#Za{(KM_~L!&F$zViJFhNLM%_B=KbNF zNvAP_eX+x{X__Yq2JDNJE0(62_VF6vt-S+7E92xQo_3)cE;SQ(d8!#V5rL;2=lJUv!a@G}LH^)Q`jQMSkpG8v zSQ|NiFnz+gb`<28dpAwt8_0_=o&rZ>ZSoW)O$ws(+Rc5%?oPI?dV~-F-Y~W8-AALI1|QZ&EF<7S3&D#!f%rCmxAr$SVdFriBN7q`%tw5>Y;}8WT z|4W!Z3YZ%Xj?MjrXdx}Va5K17+nM9kzUPR9nVxP>bsykX0BmMA3;_A7p;i}ILf0zq z8we0fLQV|Wi1NJSvx^`vim+``!vH6M#?NIKoR%PtABBhK%27H5! zXC9^psgA-RT8*DOOUhQc1i!77zG*otmv#q!A`CLqVh~YRjn^6NMhNIh0;(zfywS(F zNaM9rw%kaSvu((Nv9I>N^3Q}q_K!X*O7_N&eF8Y&@FIAq@p^0i41ryXsQd?y2#Uw8 zWCqc{WlNr^lJ`k#?i{8Y20>1chHGq^Rc?6hp9^QqKwqLz*mw9NCOKf+|hl~Vzh zi0-miHz-vB`lq8Z!2ax`*@xbDV z2PfQrr}lmGP{$UjFw(@TU*Q5(K&F-iyOXZ)q;n~_`lB4kRhg02Wn3~q4eF#y%(#Di zDZ4m(N=f++-41Xv`r%syM9jO?rWaY57}MrY4G*G9?QD+NG_GYuh0cF`!1}$un-NX9 zzQWHlY*ppYMe4P{=OT+p!<$w+{DAODMz3a9!CZjN)ND2@d+OI5bCQc7ZolkM(A15* zyV`29`cH;N$-y%9Cj!LCSnZ$SPlhM{$lFNu671BY^pl}wdoOyfetY4?pfU$6I2cv4 zkX|3c>zYW-5>ca+=O$nw!livT!&cZp3sfqLS|v7^l{Q%KcQCs58ba-_H1l zQxex$m5h?8!!_(TTdtZIEKGuS7JqV}`8%$*vl$#eH)B8nJKW8@vX(J^9zShgvRnZ}OlLn`12A=ayiF>s}tjqPc7Mj;$yu&o+OEkLeTnU9WXJSfY z^Z3TjS$u=kl{kRV6gX6$pMO_eNQoVS5?`xC)E~We zZ_|j3m<8YPnr6OGfK;o^G|mr&$6<2D=G+bwV8k5%Oi?4o3qQC9fM&qV)USl5=%~^{ zBc@{bF)@y_61+COjhYSh9Z9pk<-(OnlIGsq-2Z9JrIlQy{%l%ic{E<_h zguHxPc2wZkxAYX<1=B!90^inWA|6d(4QQAm^)m(5H(sK$36j13e2M6pZacZZ?#%Yx zTl=7*0D}!98|Y3q2F|@TO!eI@WF_tvvW$D{5bU^&dkcffPT7|t-~pD}f=v-IK+_*% z4DTssGFzOtNFQ&WCd@eMS3A+jlnfszN3j?FJ8h%DKhdIvp2)A&TVF`RjBiA*dglAJ zE`=0LG1@>jFHrPd!L&rr!z=dy&*zo5Qu{q6UTIclD!cfzyjR0&Hs;wIs+7ev15#r# zWv~63EP5oPV`TDZv$ToQErURIJtaYQPg`M`wQ)3M@~w?`RCv2;oy|}pMpSlM?J7JhEa`*(E1x!iq~uEMIcI5#Aev zqy}B0L%lH3-hot-OvWv@WRPSL&L-h&Cp4OMD>b3W!XX%o-_hr^C6URUIz*BWnw0Hta;OBSODaD71PPPY{uvn)Hn)Clm9rs?4MQkN5+%_ z&7TWRR_iNMR~@S^`lIL?|BFhlRLR1A!n@@8$i1!Cw_hq=&vXGo-6;SG0O$hc8t<2M zv?sXuyb|^aFq=Xx=YY&$l!wJ6;5pddzFO1luxQOUye z&V>z2YX1;RFO4U=e)%Pu?bPQ6C&If>Jnrqxz7!b-PesPzk6f&M8o2rxIIX2i-&IxK zl3031Z(at9?_E(>8?LJynX7*gl(I4z?+KEy$?WU3{cB>j0pr%_pRySLa9_4Ducknx z{yNo7hSuqy1Ua4(WF||u8$A8~dfp69+&_hXsuO46tT=;I6=#(4*ONbvd!NydzY2{4 zH>MG(HhGNl?C={a{^C(uC$+Z)QsTUEvL)MDcm}He;_=j*kd97d=z{?Wk_d1qWXr(0 z9R|YQ5p>v2#ti3uh2%J)Z>N~jLM1n z8lKyeuMVG<{rQY_RTy=w534Y?WHJc&aec zCUfeW`xI*FP-gGw~lArWudt}e;jFhfgZ11F=m_(e(? zA*jp1f3qBxoC?^2eBLLiq!(TS$AV!()d3~bZiK!hLqh`SfoUg@*r9@V1MpygkJqbY zcr=w`a~|S*>dXf<=>JRkyyHv^Znx1Ls`2EwyI2Rv?&8=AqJ{NBiQJWm@oRP6#JDxO zTyXrW@?|C_EFl6Ww}eb4m^QF1mlrLiFU=zeOP7vl z;D8wCviz-?&D@^h&e$Hg>)khSRb=ccCNx0a5RekZwr4Ds8%=_>N^NozmF1OWCYCh1 z%BxlRb%j0`su3?Vh2pxD2Ik@1a=Ojn81miXQcDrEO%4qGa%k)in@ooN}&x>s|ZmbZZ~8lN!oY(9u? zoMgFpm!)2)wuW@Z=E>aehwzx$wbRR|s!RP^urQ*{7w|P8da0`|V+zx-+5;lx~=R7XIG@nb|APkQ7 zE?$;5q`@xfFzRHc(eu{$eWJ=Wo$_km^=8r9TT?qTgI(=es(nO$?aqsf)_!BLYWq{z z)qYU5m008-qAvGJQ^a4Flr*{`vsL7)j?ms+0hbtG%08g+RvxIQRPIHU^P+!%pUrAU zVNIf_@qh#OjEdbsF_sCIm}f<5bWN*XJ*!d^C{@U)MNQ{O!?)IMu&Lktkwc@i&|v-q z#DD!IHMAr{gGEOF*VNYUtVU?5NTdW`_@IyNqKG(r(C5oi3+^Ea#@{Wz3s;G*bTp|FC7#i7qOwO89=U3US$HE}&0G@}ZI5F=KvGb33Uy z{1YNc`EzntlY8pVS^oN?U-(xQ{u+g1vf*{^7cwsL*L4nHo57TM*(sgRCFks#&Q$&3 z>a@=!u4FrvoT-upVubY9%~L=rdvDK)m@_#tF&M+hi#b3+m;UT1pod%Y#sM(kx5a0` zD(Ib=Kd$o5s=TFPluvsloI?-SJ)1h`L0^}YG`c$7ROg-ct$WcoEnV^!Ly_&r{x28p z$DxKwmKT{NbY&kwo+8LzXaGIMDVu+F@+P>E+x}oI!uD6BHjdF0-at27w&eoAi&M)P z2KPezjH@|6UjhpY7|}J~U(K`C!0_Y~qsmJ+f5>~{;%)e&Ghcv`Tm#C960M-)-VQM8 z_G%y$FMmf@w6hhWsmFY4`B3sa?o|WD{C`Z3@6*GNc}YG zxqFMxz$W!?`K!f8#GS<-$Vy38K1(F@Td9hR#UXXiBC&|D7@)n>#^u)Nm7>i7{IvB| zct6yob+UhG9+rpg_dE$Q>XJ)@-Sr+GEt~Mii}=Ac9|PXu2O9Sp7+)B%SEiN>7M^P$WTbwzy$gjkB!0|(WpI#^gs_{wQ$%|f z5NUQ56`7CdrTh$q(zYKUocSOdqdx?h)zTIwxD?jJuyeAkZgFhhof;A5iU#&P<1k_n zgT*E^DB!tjZw2B+YwZ=OuMb1j8oT-S5CJl=dG`RYr9*7q^)}Q4`p_&&UQO_~SZ$}H z-}|%Kn`Ta&WX-b-<6?#pyx4E3VP(r5lZhHcw(jVxA>NoY0j#LUcjB)kb+j?ZB}5aS zL>M8NbH`MBtf3Q!j^b|&f8$!PL{7LER$E-{{ps1lNm1=NkX|J%jEJOesFmMkxw+Kr zl=OuVR(#rs5atI$-{X>8ujU7FoX0fqMr@xtky^4}GEYe(!MrJQfBO%u z-zw5L`XUO~*X5mJ^S%~AiEfJy!Bn+N>Q|;dt`rkVKt~$HM6r46DAmZ)ii!i~H|wjd zMOZdga#JUNo-Ihu;NQtSPcFJ;B>T3ca7c@8bLEG<1TI}SQ5P`R{fWBlHeqtYWTn)d zNL2i3E5&EUBw6hqmd&U%>o;rJwzbKi>@@U+nF@^j+XO6dM=5uWrO2PFfCVKGnW^F7 zSsGWn`D^%BNda=gofqRs*GjM8de7qiET#L%_YnNAxCeSK5UG&<=3D4wyCQqH$USiI z{G4U~<_jrS+&ysc!kls+Ho0>7?txCuJurBgjO60(fqu{69vF_h6hXSh+`*N|&by6r zat|!AU*Yybg7^xy4szWC6ZP!72R_uYAQ{!ZjHRQ1GwB}Y%&YTR&Q}1|cMqKHXSk?P zNiX~Wc;gO(PZkdznOcW^z?{S zKT#N^&NpMBJ+?*mdTI~9dt>Ae8z+C*c=^L7;3FCqJ2CKuW&B~ zsNuJmo>k0A7XL0$-gfLln09I4OOAHAh)2^dfAzIXuWL-ZyoqGN0ko$vg0zd(bK2!) zDXm1;a)XrBF0X5pB?K1QDtLM7tb=*sYnR#fPNoHM!cfUe$qT`XyVq@>azz9#P8`d% zP)4~*dEDSGs!f1nTWSQ0!z6vs==6RdQwS#tIZMNOrhS)>J4+k!W(y&J_) zUGpmMg0Wx3Ui@IL-<5^njFK||ApgN9a){pyoJfN?c%1`8XHj0!NVc+1Lk|lLU%xV; z+$}*BaqsLB^rSg~|5+G)nhjhWHurJT@38} zuHG-wBJTPd8T)3>%(U!TNLVP^vX?(17pR)oYs1G<0=mNR5ezp=pR_u4*-c_+Id6N5 zS^N3>`HK9K^EQuJegAFV>5Sw#-QV`TTJYD1elV4#X2D`QrNpV}j-)L*JuN{Z{p&X_GpjA z#>ZQ*+=ahsw^L-Ar8-Q8ukzbn610oV++q%0ldhIa^-Xb7q7qX;i=RmS+IHY;iHe^5 zM^3RvTrpG>Wpt~KD{~WKH3RBuSLQ7%^QTOi!{_CcIo*|Ep$MECGiAPEj%45rbY(ub zGEJE>f5}CA7gq+`0XV5lnLA(1f%B8-A(E=hR?IMmbLU)qR=YB3D|29`%s07xf5MgN z=sX;edX^#v3M=*6V<8tJc_gNz@OJ{fW-)f4?It7TZ#WE{(d{Vdj7Z`r0+<-=AcqzteT0=Bt;?csnO&*dlg!GIVS!8wWLyQ`CG!Fq=*z@Pob6g$ zAZV9k0kF`iMVy0D1-34WZk=A$lEd)!kd_Wx#3esUQ?s_xu+(g?Gg!ae0;ZU_GV=nH zHYa9v#<4xywi(Lbq5K`f-vRvX$KRg(b>nY){v!NMM>UEa)z zu0cc+M;ac9i0YFF>OB`FcOujqf>s#9?;%i7gGc3_Qb7$$iq+VeSv!B@p)l30)Z~2~ zzT~ohut(@V-79`8FA>lIPcFem)2{CjRDZmJ^;aDOA0EwU!ya#&SsT4^xu}Tn>G5RS zHuE1-^@D(Hu8{K3oTms9s^*OJo_wtx6kq&;HXjYAbo2#$?*7Vci}_EhW?QSN1Rhh? zg01TSIPN_ES$+OkIhE2Z;F}dXOuwwacaf5^em{T(1rN3ZsO2Y+r(>uJmxuNTgSsfM zyTrYN*2sQI6Q@tzmffqo%l}ETj_jMQw4i*|* zxW#{XJFeQ>J1dQP0g2{nU(QU(>`K&DC|+8N*b1&bLDP<*RNqykpEwRCASFfL zrTiWOV1gJ>i{+uM0hyncA_e7KT8c20$)94f+4zt(+R{ip_MYQ0FZ#wKMJ?jxkBYl& z)n9+7N+)%dUT6jFD*Bpq`CK`N!C9eTI@Wg<6R=KRx}03ON~MIuQ4XABH5D=O>3iKy zIp%33?j1wW;fhrC0Y(_9`FHi{ThAA25^-av^ZvrTi`jQzHexI~rLQ zl8cW^fpO%dqyL0Bx)eAv{b3QoH`s$T`3g|!-M~3vI6BhsBkABB{VUu_kXzUUGtz%x zBzB}<_DGiWH(A?iFUSb;C$(o8K?bYxyW|GB;RXIvZ^4jG77Vj7c*_PwF3)HQCRCAC zNfj*xV{pAnyD>P7M*ok-U~@T3e`^eulogCYh*mc>2Fr}rZVaA%I6DSYjXt?!a4aR= z7~CnbR4@kS4sS^7i-y65r1{*RH56qhy@h1mPC~bXgzg_8DQ~MXZ`)xjJ_Eu)O0N#!f3G^LP{_P(*4ypXY9GO$=ia`adAqOP z-sj%V&%7<=Etj=kYwyE#uH6o<-ABzIPP+%YcBfIRZ`!rdP0&VJEt{bdh{~80*1jmH zzb?}}89gTe@$+m$eXtrfeKbS>wl@IAO>Jiv<))t>QoRk5^HN&vGxZNu{kJfO{AjxG zDCpSE3cmYh(9n@8_y`4=B&C|_{8N<}!m4Mnx`n>PdPoHg{9W}pZ`Wr2iK=&zt4F|Z zML#J{^>CONocoB(G>%>^_q7IR2iL<>G62R1K$!uE);_5v37*TtX%oMZ`qD2`@?@3l zoNcNkXzEi+)6|Wwscu12j~G$Pes}|1w-l~t34pFYU|N2NXtbu*f{@?Ta+S1Rovo5H ztt7|fy^7vJQeC%LBfx5XH}s>?QYN~Wngl`P9P zRT?xEaZRl?J2_evG_~eIW0742phQhg5`gbJSg(!`dbLHisUKbsdNo-kU$&CQjgnP1 zR`*aE0+zX^-q-3vWA!K3)H4FWaq2enrwc#=0IB1yW7;qA>Gs!5frJW-^IMQII?@DT zJk!#FuBBzq(nK;^8?@BUwN#w}G(&*886e~PyNmOEy9dP1YXi3YU8er^s{aA29rW6I z3RRI6(sCIcUxgqt?RKR0>QQg6n0i~gDfRYB>XAy2HPN~xuruZT3OrnKuEv^$glpN} zsk>KFC-fEpGlfNEaq_vV0y^F)>|$W&PKj<4L=E5%3ZTV3)M;M0a#tCS@))tHS24^@ zQOu7~nEwj3Bz}Y0W6`d#+7=L$(IJwd?1$Ha@xPB|sg3Y%!4%d{^M3v^_Xdtyu z(q|VA%a@&=DfoD9!9KzSB`UVL$+1nQW$_0s*SnSn1TDXEzqK6A0GyKx(A+b&?-)Jx z!J=Yw(R~^A5n@`uyB_>Ql=9aU%{S90*yvFj`=7AU8G}IfKVhTo_Eqm%vC*CxEEj`i z^G{|<{l5EVb^kp!!ZtTH(yGaeo^@ZAXI9fecn0BJ_QJ}5XIA7=^jb45E8#XX*)U&-jjS|y2pIxq^fIaFVCs=$YhE$~bk5eaKSUhbClY({#IWQhC8zo%K zAn5`w7#S`yG+aVIA=X`5C?%tZ$w4n-y?u{d=B=5HnG&8Ec9>Uvy z+S{=4c`{V#U~ROG0bnH^tkuhdI$x>I1Js$nR==+07kN=Y1OaO~ms;*s>r0e#soz!N zmfCUY=()UXwZ+zY?Gt{)D${O{zYEIp#SK%`fI@CtE^z+n+ibTj(o?6)v}=;%beO*i zlp3Qp7t3}B<)TsP#rG5cgH1}#?6O2DT(#=7Op%ptMp(D1kbf*LlNya}Z#+QDQAliT za*e^iCW{iYZLhJpnUqtf&zOYr(BGl{zrpj^oM%nCPIjJ7TSr|+5F2mzC&uy1uf;E4 zYOEESU&@>@zdU-Pa)KQ^3ypa~yT9M!L*jbA@Shj{iY;yfp|jWH*pVlOew6pJrpy@c zJC8)^BWAJ$xyz2V7yk;J_*w6u2^4R=0f%3u& z?&9}V{I2%Op5QkEsmAgTC-0Wp*&q_fQ7oUCeQ3cS!vR~J7;q3!#NK;?wp}d5&f6F& z4ffV)>uqG?rwB#P>&BU+`;=;uZmp>d8r%0>XdexBtm#UX*qjnth2OZFHEXF16!UYh z55@|8(hZyoVt)FrFPz14E`fBVvekTwzP5}3Ro)T(QdJG6JW3irGt{nE!!v-%$BKr9 z(mDPjn9PAThog}P@?-N3z!l+>M1x95(&q;1R)MMnR62UlU79X(T<|qzU+>k|J^2c0 z;c}f(>hO0Rz34<)v{_K@ew9n_V&!_fa(B#DxwSL%$~~rXZ@F@%x$x%Xm-~mxJxV!T zt#ePR*nhf3jX^J6+9!q;4&3F(KU=dQAhqdQ{@iHFZYJZ?N2$a zsO^}f7p-MZYY%bT?v8{Nx%B&|Duh&_z|3PX8E_+c?zt;C_h|O+6>@mFj+aiH>GS+9 zaHU?N%%N7zaa_i5WaBqB)?cY7F6#nMnD67^l9*uN<^)D-2bpkJ`L{k!C0YnJNY!o>pNkq&GV>kvWGp^ z51Jn_V9}RgM@+d)Fzr>hX0R)1{Fh<3cNJ~l0$An&W9LTOW~=-Ddwsuz?{3y$NJL8^ zQaXB^8|eVfzAAU5p+~rg(gTgr7P}Xnd#g(SKEL#SD!sdvj-L6bZ_uttb=cKmz$!xW z!eP)`Wq;U_ju!~K!r7rM@p$t;4Jvs&Qsbuha^m0C(<;Gv6gXUJWAZHAO-$jm!}myZ zi`Y0^N&}L)c)+rQc(j|*9zp`>X0)=q`H|5Jbr$6mUTw3Pb5e=uLsAWiPFuVt@vbSIb!_>qP`gOp_a6Fa*xu}e6JC5Y5d5NCLyZ~vwsvotQ&!I%u=E78a( z>v7zISna(NT!F~#5AMJbsbKykBV&RUk}r6F%dexuVO&02i+)8F${W0eL_4ce-p926 z%*ejvTJToZ$UV%WvOM$x16EfjfijHfygA&8*p_I~#}IRP$1AW!=16Ie;m5+mviF&# z-sqagLyq#JMftKFv_(@S%8Ynf@E&Ez2X`3WOY4z_r$DaCE4;(-4nx`D^(r{&4#T!S zQc&3;mA$>N_05H~?fWimXQALUe0b(f45`eo@JakK`@uIVsuD+F4b@CfZM@uOT9?N4 zVqLhkBG%*qLhgzIK#9~#9RT5B=DI)QRv}Jp#$C~vH{&kg(PmtK1V;-=e!BMNM@B2P zvyIO1SOa7;E+M&`2p#ByX*J^>U>@0w8*Vr(OI7SpIOF=e88?~!G2Os=FcU^I&L-PW z!DQ=4tV|cJ6ZX^8vZQH*CHm7USf$78mJ^#(f}uzh@~W^nEf1XsCUwXV9lK19NNG-S z8^cF6oaFoB^kLI$`Y=Qc5TL;Q6iZC}wFjHXQf!Ucd0^-??ghTv^f-tlT2{ln3$e|<3 z#bNra!2b>Kg~}v{&)v*++Q&wcusXT@+?4r!F1AU)sdI5b^g{dIK+kOIbmtczs=Q;! zXnVx4xVJ?-8N-qzgWJGP-p#WZqIhBpx$Ri5ybO4Mibdvr+%+=wZFW!6(RDtZFd=Q< zAlmq&_|{Fgf2t#|ZKLOjvt+`@%fpZU1%4y?EWDl{cqS%G{U@VS%nD#te+Wo5wwEq+ zFuo9sBrrIyefHm&Rov{zMea4CsxE|2?SBveoHf6F-=%(4$PjD#QdN(lDsqJ?N~7hC zV7Xd3i>lD-eZfLEVH+?O22YKSNevnx(GjV?zoTycCKHO=v8kD2S-3fMGo{$tzUF2f z^)QG^$ES;WS}*9mA*4}T%8nuCU&{62cp1&+Zb+*f5|p%PqB`(cg@#H*ZV|>bzY$peeBroLj@MGT0c%7Zh&37 zi(t>T??OIV^G?J_2_mKNl(W1WX4|#B0TGZ~@iPI*OM=!i+qDZIlOy@L&<%_mRtZmS z*zOAToi*Y`&odKjD6^>O5X_vBHw0g~J%zhz?LQrY(|i3lhG5q&YA$~W&QzP57=m5J z3wcBE0SFsW7=oX#Yc&M37@=SY+8E&cArM*Of;fSpuu(`-{Hq>VG@Tee13L954F9ZTc4SzbS(3HiNN1I`hdY6OWwyXZdlrFOAe>8AhSPxW?q;#A9BSahp zUetJXSOn`8crlS)a#L}KYVRA(>%72=$|=5Yds}?la!^~~MfUKFGCGW)%<|OhQIVa| zU?LBq!B%eCxYyCbsXEHA%n=E0`gzeSZ&61ULpkM{!rA*cxQcGK3;hCLIdqKoT}60H zdFX0mLKjqVgi+5?@~mVbCA(14QSv|`h)6^@ngwN)d|*Z%CAZbV=qQm+Ro*15+pn5O z$$uRE`I;weOs6$ba`YmZNL)aj5Yn8Vpw<1&}wv-koi^~u|NYNW%HOH_|qF-JUP&XYN1(ift zoEF6h+tV@cmDl2#p~HLorQbu4)hG=IR^iIjwp;td&E!)^OcD2;xJB|`|Cx~M_K~v> z>)vEZo{4V)!7}=Zr&gjD$ZG;&LAIeUjTCahCUiD=vrNM(*6_A6SN&M7yeKr4SORQ9 zNw-$YRo)NH-lOucd+t<^n7Xd zxkArMqU3-7gPxDma~sO*_KXMhrY85zZF*C#H=7yESM|J4_W5}|@5HmLk#UVbG19T7 zZ}hT5!OJi7Qd!(w$zQDGhkE&5!OOSwaxpLcHXHT)te#z^$Mt-_o`rX;>92ZL=$!xk z8a-c`eV)p5OP&AmQaz0GAI{gq@&3bkdN{)G!YO))`46M?@JF9&`{-d$e+b&?fuj$w zfiw14x{Qf6eUGtcEGh4V68a8#Qe6BSTo9=ru(|kdFQPpA>KB@usnxuv{SM!Vuial3 zKEz_rJa)Uu6_@qcZ6hz;C-fR~_6#IU^Q-o|>+$@~EDk@rT627faI3)TI>f-5%kpTz z;;~!K=BYe(=i{-Xz_kg428VSc4Kl#1oN30z$o8O32duI+4jP$2%z2_~+I6k0F3n*D zB~xu#>fj#qAK@bvNZawcx~!?Dbwa#lEP4-#rw++--kg#3oqszV&Tw|Y!W5u;x3CTb z4$w%$NMxmzjx|}qZ?KDO5#cRO&5DTXW>LFll^Jy@OB+FtHSHFTQFt}71SHP~^Fv%ZjQA(FRTOTSF1`r;ahl}yfaKLY(cf`!PwZj+uDqFj zDj@r7&hXre*sP>O&D=AKG79bVI+xodxI`;4h?PEzGW;bK(;MqSDbYBE|B^-uqwBI^ z{FU<8lfT~l_2aKX!`#k{r9oq~E2Jb)EVOT~PFyxB^UdQz$U);MKAyh`>1blQGYxWe z59nTsv5S{$hL%gLJb>LPKAFhme2pI&hvlMa z>hcDv?k2d-pMNpnxXP`>fTe5MLL;VL4mK~k?KP@Aw4%V&9w?^a41?lY8>}>C7 zTsKg>Qw5L6x4F8bYmKd|M{>XK#dq>V)r;BJQXigmwFj$qXTE~qx9m^p<^a|$SXu|h zy^C2mDG4~S$2#V(LD?W8=NJS|vGO(bknc*aXdzx2N7>5MCBFlnNd|c#1M7T9C)Qfb zW?z{W=uu_}+EZH*0fxhc;hEwQ%?+%JU`eKn$t#cyebcFL&NPGFW|ZsKF{;(qxRg?c zaj@Wn$dAIEnfaJUYumP)1GnWaF&9qtJCgBIx<-ywBP%3Xyih%~jrSkasjicb?0Y}A z?16Z}F87B&hvdhrmI7w11GpdUg!$6crJJ`JofA~_Pu4)IUYMlFQiDu*%?H!pT)aC8 zZ<)5)@g6IPJ2{j$6UvOYMjIE$#b#F@QteIFXfp-LXP{}6Gunhs!PpXE^RdBXR>Mwp zJ7!Hc9o4f_-4ji&uJwtGS1QtQm?Wzs+y%md)jlLByX;Dif1HafFiSps&TJtSPGa&} z_z6J(sdXo{o~X7(8*3^Pq{D$!<4vky63+jd)D9EZ1c1%mxu_tUyL;V`ox9auj~#hz zzD|P03%|sYO{wX-&bPIjzaQ1fpD$kMbin#^_iVsbCwjcc5=qWBZdz9|;Wr=(@$L}Z z-+(@%ac8I;YnmYhWn`tJ*K2+;cga-riU0LleRb!MmZf%RZwvrbCas(=zrK)NnTnhJmFfNU>PFEu{Cn)(WMqSD{1zei4Ykoe4`0C$*t&5W zD3m&}FI|!1l>#>Qa#e0sm3eB=+~BMuGI1TImg#wF;OQCd=PKQyO4Dp0(A;@*6}&6h z0XS4hGjDHdkaEeSfC|!`l!ALcHeHSOvjI$tE&Im3Z=3grie>~~RMEV*etTWpP%qYW zQk)0;WW$)ajc+@q{OkcBO1}v#V!0A+z@Jw+lYeIxJ*IE{Yi)m<*RuF)G*e*^%_iKp zn+VRyy$&Or7eL`Nd$9PhyZ~>do*b=#oj6neyAx*E+Nx++kak+4f#njMLbl>TeAh9y zKGTgGFJXI@=oHlYu>eor)?LvwRo?Nq7B1{pBa1WXV^bmmtu1?E6p)bkMINT?C)svVuJ6j2f5hA}#gJ}N$G(>qv(K5Huo%J(VDWs~t`xLd|g?s)Lb^DbLuY5&X zKc(z*R#iVFu6{q57eZ~33I+1MwISKNpxpYeTh7d zC(1$wX}vBL?$E*&09`e#T83Y3w!q5NQyVv<3cg~j*o%1Q+uE>0TiBt9aCzY}AUGD? z8g=!`y^`A_3|RvK$qbnWb&9! z?hF(r3-RUd4AyQ6iPk2E46k(s2CCZ~q=fbZPl9vEzF=G#`bexo%sUGS6j^0*NQgU+ z1;$=V*(DI}C*Hc=KkssK0D7yHs{La(qSV z$SnOYjWyi>WG2=hiTx|Cm&v5DRqJ6uaj+yQ$Ru8@(+Zb8!TBza$+@8Pu#7u1(7c5U zoIq^`ZcTb}-Nhi8#@z$LQwh(CH4O%Pcdgc`1PjOJ^pxSk6*<2i?V^3J={`lHfvWXR z(0seCySZVmSTsX~&WZgku3z`PM3roo{lB7LKf6fq1O2+jJq7ypTNGkOzs`dlq!LVn z7uT=1$Ufe*e%-qS{n}$IU%!4JhWZWtI+_Ips^>*PajD1AwWI^nu1qF-;L z4-38kIQn(%ofIkH5vN}}053LYAE#fB9R7btzZxfyFZFw{l7405mmV%l7FVtw`pA^) zVOqOnm1{YVrd*Gk>?_wJ`H@ks+lobzqF(3%0Q<`I5MZHP+Zd#*a$Tq~m2y4RSFR&} z$ST*NdCK)(c%g`LJ-t?~WwgL~cW6#*#bpi6XXh!`XD%yReNU^tCQu^1t@<{q{`=y} zb;~;1`#(~yvwx;*n^LYHq}A^n<$B-k>d0=w1iADZ%Juf*9XsMe(IwNdkp`}Zz`<*L z36$%Q3yabvV%0Nb?PAsURP}9(V8d9iSB3wfa%~IeL>i__E}=(Fv7(t!QtjjWylUDM z;ayarmcTYy9n@cVj`