From 1d49bddcb363c6c6e730c631772ff9616c87173c Mon Sep 17 00:00:00 2001 From: praveenkumar911 Date: Thu, 4 Sep 2025 15:35:49 +0530 Subject: [PATCH 01/18] removed barrier --- app.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/app.py b/app.py index f411127..fbd15b2 100644 --- a/app.py +++ b/app.py @@ -340,14 +340,10 @@ async def get_program_tickets_user(): else: labels = [label for label in labels if label != 'C4GT Community'] - contributors_data = issue["contributors_registration"] - if contributors_data: - contributors_name = contributors_data["name"] - if contributors_name: - pass - else: - contributors_url = contributors_data["github_url"].split('/') - contributors_name = contributors_url[-1] if contributors_url else None + # Get assignee from issue data directly + assignee = None + if issue["issue"].get("assignee"): + assignee = issue["issue"]["assignee"] res = { "created_at": issue["issue"]["created_at"] if issue["issue"]["created_at"] else None, @@ -365,9 +361,9 @@ async def get_program_tickets_user(): "domain": issue["issue"]["domain"], "organization": issue["org"]["name"], "closed_at": "2024-08-06T06:59:10+00:00", - "assignees": contributors_name if contributors_data else None, + "assignees": assignee, "project_type": project_type if reqd_skills else None, - "is_assigned": True if contributors_data else False + "is_assigned": bool(assignee) } issue_result.append(res) From 19f09b2d01ee7fcf931639452faa5010370d9386 Mon Sep 17 00:00:00 2001 From: praveenkumar911 Date: Thu, 4 Sep 2025 16:33:16 +0530 Subject: [PATCH 02/18] reverting to old code --- app.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app.py b/app.py index fbd15b2..51dd330 100644 --- a/app.py +++ b/app.py @@ -307,7 +307,6 @@ async def get_role_master(): role_masters = await ServerQueries().readAll("role_master") print('role master ', role_masters) return role_masters.data - @app.route("/program-tickets-user", methods = ['POST']) async def get_program_tickets_user(): try: @@ -340,10 +339,14 @@ async def get_program_tickets_user(): else: labels = [label for label in labels if label != 'C4GT Community'] - # Get assignee from issue data directly - assignee = None - if issue["issue"].get("assignee"): - assignee = issue["issue"]["assignee"] + contributors_data = issue["contributors_registration"] + if contributors_data: + contributors_name = contributors_data["name"] + if contributors_name: + pass + else: + contributors_url = contributors_data["github_url"].split('/') + contributors_name = contributors_url[-1] if contributors_url else None res = { "created_at": issue["issue"]["created_at"] if issue["issue"]["created_at"] else None, @@ -361,9 +364,9 @@ async def get_program_tickets_user(): "domain": issue["issue"]["domain"], "organization": issue["org"]["name"], "closed_at": "2024-08-06T06:59:10+00:00", - "assignees": assignee, + "assignees": contributors_name if contributors_data else None, "project_type": project_type if reqd_skills else None, - "is_assigned": bool(assignee) + "is_assigned": True if contributors_data else False } issue_result.append(res) @@ -371,7 +374,6 @@ async def get_program_tickets_user(): except Exception as e: print('Exception occured in getting users leaderboard data ', e) return 'failed' - @app.route('/migrate-tickets') async def migrate_tickets(): try: From a11765850bc2b62f4595102954895453af76b263 Mon Sep 17 00:00:00 2001 From: praveenkumar911 Date: Fri, 5 Sep 2025 16:31:24 +0530 Subject: [PATCH 03/18] modified contributor --- app.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/app.py b/app.py index 51dd330..4c956a5 100644 --- a/app.py +++ b/app.py @@ -339,14 +339,8 @@ async def get_program_tickets_user(): else: labels = [label for label in labels if label != 'C4GT Community'] - contributors_data = issue["contributors_registration"] - if contributors_data: - contributors_name = contributors_data["name"] - if contributors_name: - pass - else: - contributors_url = contributors_data["github_url"].split('/') - contributors_name = contributors_url[-1] if contributors_url else None + # Get assignee directly from issue data + assignee = issue["issue"].get("assignee") res = { "created_at": issue["issue"]["created_at"] if issue["issue"]["created_at"] else None, @@ -364,9 +358,9 @@ async def get_program_tickets_user(): "domain": issue["issue"]["domain"], "organization": issue["org"]["name"], "closed_at": "2024-08-06T06:59:10+00:00", - "assignees": contributors_name if contributors_data else None, + "assignees": assignee, "project_type": project_type if reqd_skills else None, - "is_assigned": True if contributors_data else False + "is_assigned": bool(assignee) } issue_result.append(res) @@ -374,6 +368,8 @@ async def get_program_tickets_user(): except Exception as e: print('Exception occured in getting users leaderboard data ', e) return 'failed' + + @app.route('/migrate-tickets') async def migrate_tickets(): try: From 4f4aea806f94478554a61efebb2aae9bc42de2d1 Mon Sep 17 00:00:00 2001 From: praveenkumar911 Date: Fri, 5 Sep 2025 18:20:57 +0530 Subject: [PATCH 04/18] bug testing --- app.py | 28 +++++++++++++++------------- cronjob/cronjob.py | 3 ++- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app.py b/app.py index b406227..0b8af0d 100644 --- a/app.py +++ b/app.py @@ -156,7 +156,7 @@ async def fetch_github_issues_from_repo(owner, repo): ] @app.route("/") async def hello_world(): - return "Welcome to C4GT Server" + return "hello world" @app.route("/verify/") async def verify(githubUsername): @@ -307,6 +307,7 @@ async def get_role_master(): role_masters = await ServerQueries().readAll("role_master") print('role master ', role_masters) return role_masters.data + @app.route("/program-tickets-user", methods = ['POST']) async def get_program_tickets_user(): try: @@ -339,8 +340,14 @@ async def get_program_tickets_user(): else: labels = [label for label in labels if label != 'C4GT Community'] - # Get assignee directly from issue data - assignee = issue["issue"].get("assignee") + contributors_data = issue["contributors_registration"] + if contributors_data: + contributors_name = contributors_data["name"] + if contributors_name: + pass + else: + contributors_url = contributors_data["github_url"].split('/') + contributors_name = contributors_url[-1] if contributors_url else None res = { "created_at": issue["issue"]["created_at"] if issue["issue"]["created_at"] else None, @@ -358,9 +365,9 @@ async def get_program_tickets_user(): "domain": issue["issue"]["domain"], "organization": issue["org"]["name"], "closed_at": "2024-08-06T06:59:10+00:00", - "assignees": assignee, + "assignees": contributors_name if contributors_data else None, "project_type": project_type if reqd_skills else None, - "is_assigned": bool(assignee) + "is_assigned": True if contributors_data else False } issue_result.append(res) @@ -368,7 +375,7 @@ async def get_program_tickets_user(): except Exception as e: print('Exception occured in getting users leaderboard data ', e) return 'failed' - + @app.route('/migrate-tickets') async def migrate_tickets(): try: @@ -410,14 +417,9 @@ async def start_scheduler(): scheduler.add_job(CronJob().main, "cron", hour=2, minute=0) scheduler.start() + @app.route('/trigger-cron') async def trigger_cron(): - provided_password = request.args.get('password') - print(f"Provided password: {provided_password}") # Log the password - expected_password = "c4gt_tech" - print(f"Expected password: {expected_password}") - if provided_password != expected_password: - return 'forbidden', 403 from_date = request.args.get('from') to_date = request.args.get('to') cronjob = CronJob() @@ -426,4 +428,4 @@ async def trigger_cron(): if __name__ == '__main__': - app.run() + app.run() \ No newline at end of file diff --git a/cronjob/cronjob.py b/cronjob/cronjob.py index c34449d..35b1243 100644 --- a/cronjob/cronjob.py +++ b/cronjob/cronjob.py @@ -39,7 +39,8 @@ def __init__(self): def get_github_jwt(self): pem = os.getenv('pem_file') client_id = os.getenv('client_id') - + print('pem file ', pem) + print('client id ', client_id) try: with open(pem, 'rb') as pem_file: signing_key = pem_file.read() From 9290e3807785ebf21cc9a1b17cb6d51c7e6c6538 Mon Sep 17 00:00:00 2001 From: praveenkumar911 Date: Fri, 5 Sep 2025 20:26:21 +0530 Subject: [PATCH 05/18] changed varibale of .env --- cronjob/cronjob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cronjob/cronjob.py b/cronjob/cronjob.py index 35b1243..6612cc3 100644 --- a/cronjob/cronjob.py +++ b/cronjob/cronjob.py @@ -37,8 +37,8 @@ def __init__(self): self.jwt_generator = NewGenerateJWT() def get_github_jwt(self): - pem = os.getenv('pem_file') - client_id = os.getenv('client_id') + pem = os.getenv('PEM_FILE') + client_id = os.getenv('CLIENT_ID') print('pem file ', pem) print('client id ', client_id) try: From f389e53344a8df95168dc97b56693db40da8e6a8 Mon Sep 17 00:00:00 2001 From: praveenkumar911 Date: Sat, 6 Sep 2025 13:43:15 +0530 Subject: [PATCH 06/18] dev revert --- serverenv/bin/Activate.ps1 | 241 - serverenv/bin/activate | 66 - serverenv/bin/activate.csh | 25 - serverenv/bin/activate.fish | 64 - serverenv/bin/flask | 7 - serverenv/bin/hypercorn | 7 - serverenv/bin/pip | 8 - serverenv/bin/pip3 | 8 - serverenv/bin/pip3.9 | 8 - serverenv/bin/python | 1 - serverenv/bin/python3 | 1 - serverenv/bin/python3.9 | 1 - serverenv/bin/quart | 7 - .../MarkupSafe-3.0.2.dist-info/INSTALLER | 1 - .../MarkupSafe-3.0.2.dist-info/LICENSE.txt | 28 - .../MarkupSafe-3.0.2.dist-info/METADATA | 92 - .../MarkupSafe-3.0.2.dist-info/RECORD | 14 - .../MarkupSafe-3.0.2.dist-info/WHEEL | 5 - .../MarkupSafe-3.0.2.dist-info/top_level.txt | 1 - .../site-packages/_distutils_hack/__init__.py | 128 - .../site-packages/_distutils_hack/override.py | 1 - .../aiofiles-24.1.0.dist-info/INSTALLER | 1 - .../aiofiles-24.1.0.dist-info/METADATA | 318 - .../aiofiles-24.1.0.dist-info/RECORD | 26 - .../aiofiles-24.1.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 202 - .../aiofiles-24.1.0.dist-info/licenses/NOTICE | 2 - .../site-packages/aiofiles/__init__.py | 22 - .../python3.9/site-packages/aiofiles/base.py | 69 - .../python3.9/site-packages/aiofiles/os.py | 58 - .../site-packages/aiofiles/ospath.py | 30 - .../aiofiles/tempfile/__init__.py | 357 - .../aiofiles/tempfile/temptypes.py | 69 - .../aiofiles/threadpool/__init__.py | 139 - .../aiofiles/threadpool/binary.py | 104 - .../site-packages/aiofiles/threadpool/text.py | 64 - .../aiofiles/threadpool/utils.py | 72 - .../blinker-1.9.0.dist-info/INSTALLER | 1 - .../blinker-1.9.0.dist-info/LICENSE.txt | 20 - .../blinker-1.9.0.dist-info/METADATA | 60 - .../blinker-1.9.0.dist-info/RECORD | 12 - .../blinker-1.9.0.dist-info/WHEEL | 4 - .../site-packages/blinker/__init__.py | 17 - .../site-packages/blinker/_utilities.py | 64 - .../python3.9/site-packages/blinker/base.py | 512 - .../python3.9/site-packages/blinker/py.typed | 0 .../click-8.1.8.dist-info/INSTALLER | 1 - .../click-8.1.8.dist-info/LICENSE.txt | 28 - .../click-8.1.8.dist-info/METADATA | 74 - .../click-8.1.8.dist-info/RECORD | 38 - .../site-packages/click-8.1.8.dist-info/WHEEL | 4 - .../python3.9/site-packages/click/__init__.py | 75 - .../python3.9/site-packages/click/_compat.py | 623 -- .../site-packages/click/_termui_impl.py | 788 -- .../site-packages/click/_textwrap.py | 49 - .../site-packages/click/_winconsole.py | 279 - .../lib/python3.9/site-packages/click/core.py | 3047 ------ .../site-packages/click/decorators.py | 562 -- .../site-packages/click/exceptions.py | 296 - .../site-packages/click/formatting.py | 301 - .../python3.9/site-packages/click/globals.py | 67 - .../python3.9/site-packages/click/parser.py | 531 - .../python3.9/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 603 -- .../python3.9/site-packages/click/termui.py | 784 -- .../python3.9/site-packages/click/testing.py | 483 - .../python3.9/site-packages/click/types.py | 1093 --- .../python3.9/site-packages/click/utils.py | 624 -- .../site-packages/distutils-precedence.pth | 1 - .../exceptiongroup-1.3.0.dist-info/INSTALLER | 1 - .../exceptiongroup-1.3.0.dist-info/METADATA | 159 - .../exceptiongroup-1.3.0.dist-info/RECORD | 18 - .../exceptiongroup-1.3.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 73 - .../site-packages/exceptiongroup/__init__.py | 46 - .../site-packages/exceptiongroup/_catch.py | 138 - .../exceptiongroup/_exceptions.py | 336 - .../exceptiongroup/_formatting.py | 601 -- .../site-packages/exceptiongroup/_suppress.py | 55 - .../site-packages/exceptiongroup/_version.py | 21 - .../site-packages/exceptiongroup/py.typed | 0 .../flask-3.1.1.dist-info/INSTALLER | 1 - .../flask-3.1.1.dist-info/METADATA | 89 - .../flask-3.1.1.dist-info/RECORD | 57 - .../site-packages/flask-3.1.1.dist-info/WHEEL | 4 - .../flask-3.1.1.dist-info/entry_points.txt | 3 - .../licenses/LICENSE.txt | 28 - .../python3.9/site-packages/flask/__init__.py | 61 - .../python3.9/site-packages/flask/__main__.py | 3 - .../lib/python3.9/site-packages/flask/app.py | 1536 --- .../site-packages/flask/blueprints.py | 128 - .../lib/python3.9/site-packages/flask/cli.py | 1135 --- .../python3.9/site-packages/flask/config.py | 367 - .../lib/python3.9/site-packages/flask/ctx.py | 449 - .../site-packages/flask/debughelpers.py | 178 - .../python3.9/site-packages/flask/globals.py | 51 - .../python3.9/site-packages/flask/helpers.py | 634 -- .../site-packages/flask/json/__init__.py | 170 - .../site-packages/flask/json/provider.py | 215 - .../python3.9/site-packages/flask/json/tag.py | 327 - .../python3.9/site-packages/flask/logging.py | 79 - .../python3.9/site-packages/flask/py.typed | 0 .../site-packages/flask/sansio/README.md | 6 - .../site-packages/flask/sansio/app.py | 964 -- .../site-packages/flask/sansio/blueprints.py | 632 -- .../site-packages/flask/sansio/scaffold.py | 792 -- .../python3.9/site-packages/flask/sessions.py | 399 - .../python3.9/site-packages/flask/signals.py | 17 - .../site-packages/flask/templating.py | 219 - .../python3.9/site-packages/flask/testing.py | 298 - .../python3.9/site-packages/flask/typing.py | 93 - .../python3.9/site-packages/flask/views.py | 191 - .../python3.9/site-packages/flask/wrappers.py | 257 - .../h11-0.16.0.dist-info/INSTALLER | 1 - .../h11-0.16.0.dist-info/METADATA | 202 - .../site-packages/h11-0.16.0.dist-info/RECORD | 29 - .../site-packages/h11-0.16.0.dist-info/WHEEL | 5 - .../h11-0.16.0.dist-info/licenses/LICENSE.txt | 22 - .../h11-0.16.0.dist-info/top_level.txt | 1 - .../python3.9/site-packages/h11/__init__.py | 62 - .../lib/python3.9/site-packages/h11/_abnf.py | 132 - .../site-packages/h11/_connection.py | 659 -- .../python3.9/site-packages/h11/_events.py | 369 - .../python3.9/site-packages/h11/_headers.py | 282 - .../python3.9/site-packages/h11/_readers.py | 250 - .../site-packages/h11/_receivebuffer.py | 153 - .../lib/python3.9/site-packages/h11/_state.py | 365 - .../lib/python3.9/site-packages/h11/_util.py | 135 - .../python3.9/site-packages/h11/_version.py | 16 - .../python3.9/site-packages/h11/_writers.py | 145 - .../lib/python3.9/site-packages/h11/py.typed | 1 - .../h2-4.2.0.dist-info/INSTALLER | 1 - .../site-packages/h2-4.2.0.dist-info/LICENSE | 21 - .../site-packages/h2-4.2.0.dist-info/METADATA | 128 - .../site-packages/h2-4.2.0.dist-info/RECORD | 29 - .../site-packages/h2-4.2.0.dist-info/WHEEL | 5 - .../h2-4.2.0.dist-info/top_level.txt | 1 - .../python3.9/site-packages/h2/__init__.py | 6 - .../lib/python3.9/site-packages/h2/config.py | 212 - .../python3.9/site-packages/h2/connection.py | 2112 ---- .../lib/python3.9/site-packages/h2/errors.py | 77 - .../lib/python3.9/site-packages/h2/events.py | 639 -- .../python3.9/site-packages/h2/exceptions.py | 194 - .../site-packages/h2/frame_buffer.py | 161 - .../lib/python3.9/site-packages/h2/py.typed | 0 .../python3.9/site-packages/h2/settings.py | 331 - .../lib/python3.9/site-packages/h2/stream.py | 1417 --- .../python3.9/site-packages/h2/utilities.py | 696 -- .../lib/python3.9/site-packages/h2/windows.py | 133 - .../hpack-4.1.0.dist-info/INSTALLER | 1 - .../hpack-4.1.0.dist-info/LICENSE | 21 - .../hpack-4.1.0.dist-info/METADATA | 118 - .../hpack-4.1.0.dist-info/RECORD | 23 - .../site-packages/hpack-4.1.0.dist-info/WHEEL | 5 - .../hpack-4.1.0.dist-info/top_level.txt | 1 - .../python3.9/site-packages/hpack/__init__.py | 23 - .../site-packages/hpack/exceptions.py | 53 - .../python3.9/site-packages/hpack/hpack.py | 654 -- .../python3.9/site-packages/hpack/huffman.py | 64 - .../site-packages/hpack/huffman_constants.py | 285 - .../site-packages/hpack/huffman_table.py | 4741 --------- .../python3.9/site-packages/hpack/py.typed | 0 .../python3.9/site-packages/hpack/struct.py | 50 - .../python3.9/site-packages/hpack/table.py | 237 - .../hypercorn-0.17.3.dist-info/INSTALLER | 1 - .../hypercorn-0.17.3.dist-info/LICENSE | 22 - .../hypercorn-0.17.3.dist-info/METADATA | 159 - .../hypercorn-0.17.3.dist-info/RECORD | 86 - .../hypercorn-0.17.3.dist-info/WHEEL | 4 - .../entry_points.txt | 3 - .../site-packages/hypercorn/__init__.py | 5 - .../site-packages/hypercorn/__main__.py | 308 - .../site-packages/hypercorn/app_wrappers.py | 163 - .../hypercorn/asyncio/__init__.py | 46 - .../hypercorn/asyncio/lifespan.py | 124 - .../site-packages/hypercorn/asyncio/run.py | 242 - .../site-packages/hypercorn/asyncio/statsd.py | 26 - .../hypercorn/asyncio/task_group.py | 74 - .../hypercorn/asyncio/tcp_server.py | 140 - .../hypercorn/asyncio/udp_server.py | 68 - .../hypercorn/asyncio/worker_context.py | 78 - .../site-packages/hypercorn/config.py | 408 - .../site-packages/hypercorn/events.py | 25 - .../site-packages/hypercorn/logging.py | 202 - .../hypercorn/middleware/__init__.py | 14 - .../hypercorn/middleware/dispatcher.py | 108 - .../hypercorn/middleware/http_to_https.py | 67 - .../hypercorn/middleware/proxy_fix.py | 79 - .../hypercorn/middleware/wsgi.py | 49 - .../hypercorn/protocol/__init__.py | 96 - .../hypercorn/protocol/events.py | 66 - .../site-packages/hypercorn/protocol/h11.py | 322 - .../site-packages/hypercorn/protocol/h2.py | 401 - .../site-packages/hypercorn/protocol/h3.py | 156 - .../hypercorn/protocol/http_stream.py | 261 - .../site-packages/hypercorn/protocol/quic.py | 157 - .../hypercorn/protocol/ws_stream.py | 385 - .../site-packages/hypercorn/py.typed | 1 - .../python3.9/site-packages/hypercorn/run.py | 145 - .../site-packages/hypercorn/statsd.py | 96 - .../site-packages/hypercorn/trio/__init__.py | 52 - .../site-packages/hypercorn/trio/lifespan.py | 110 - .../site-packages/hypercorn/trio/run.py | 138 - .../site-packages/hypercorn/trio/statsd.py | 16 - .../hypercorn/trio/task_group.py | 78 - .../hypercorn/trio/tcp_server.py | 139 - .../hypercorn/trio/udp_server.py | 54 - .../hypercorn/trio/worker_context.py | 83 - .../site-packages/hypercorn/typing.py | 375 - .../site-packages/hypercorn/utils.py | 219 - .../hyperframe-6.1.0.dist-info/INSTALLER | 1 - .../hyperframe-6.1.0.dist-info/LICENSE | 21 - .../hyperframe-6.1.0.dist-info/METADATA | 98 - .../hyperframe-6.1.0.dist-info/RECORD | 15 - .../hyperframe-6.1.0.dist-info/WHEEL | 5 - .../hyperframe-6.1.0.dist-info/top_level.txt | 1 - .../site-packages/hyperframe/__init__.py | 6 - .../site-packages/hyperframe/exceptions.py | 61 - .../site-packages/hyperframe/flags.py | 47 - .../site-packages/hyperframe/frame.py | 937 -- .../site-packages/hyperframe/py.typed | 0 .../INSTALLER | 1 - .../METADATA | 134 - .../importlib_metadata-8.7.0.dist-info/RECORD | 33 - .../importlib_metadata-8.7.0.dist-info/WHEEL | 5 - .../licenses/LICENSE | 202 - .../top_level.txt | 1 - .../importlib_metadata/__init__.py | 1175 --- .../importlib_metadata/_adapters.py | 135 - .../importlib_metadata/_collections.py | 34 - .../importlib_metadata/_compat.py | 56 - .../importlib_metadata/_functools.py | 104 - .../importlib_metadata/_itertools.py | 171 - .../site-packages/importlib_metadata/_meta.py | 71 - .../site-packages/importlib_metadata/_text.py | 99 - .../importlib_metadata/_typing.py | 15 - .../importlib_metadata/compat/__init__.py | 0 .../importlib_metadata/compat/py311.py | 22 - .../importlib_metadata/compat/py39.py | 42 - .../importlib_metadata/diagnose.py | 21 - .../site-packages/importlib_metadata/py.typed | 0 .../itsdangerous-2.2.0.dist-info/INSTALLER | 1 - .../itsdangerous-2.2.0.dist-info/LICENSE.txt | 28 - .../itsdangerous-2.2.0.dist-info/METADATA | 60 - .../itsdangerous-2.2.0.dist-info/RECORD | 22 - .../itsdangerous-2.2.0.dist-info/WHEEL | 4 - .../site-packages/itsdangerous/__init__.py | 38 - .../site-packages/itsdangerous/_json.py | 18 - .../site-packages/itsdangerous/encoding.py | 54 - .../site-packages/itsdangerous/exc.py | 106 - .../site-packages/itsdangerous/py.typed | 0 .../site-packages/itsdangerous/serializer.py | 406 - .../site-packages/itsdangerous/signer.py | 266 - .../site-packages/itsdangerous/timed.py | 228 - .../site-packages/itsdangerous/url_safe.py | 83 - .../jinja2-3.1.6.dist-info/INSTALLER | 1 - .../jinja2-3.1.6.dist-info/METADATA | 84 - .../jinja2-3.1.6.dist-info/RECORD | 57 - .../jinja2-3.1.6.dist-info/WHEEL | 4 - .../jinja2-3.1.6.dist-info/entry_points.txt | 3 - .../licenses/LICENSE.txt | 28 - .../site-packages/jinja2/__init__.py | 38 - .../site-packages/jinja2/_identifier.py | 6 - .../site-packages/jinja2/async_utils.py | 99 - .../python3.9/site-packages/jinja2/bccache.py | 408 - .../site-packages/jinja2/compiler.py | 1998 ---- .../site-packages/jinja2/constants.py | 20 - .../python3.9/site-packages/jinja2/debug.py | 191 - .../site-packages/jinja2/defaults.py | 48 - .../site-packages/jinja2/environment.py | 1672 ---- .../site-packages/jinja2/exceptions.py | 166 - .../lib/python3.9/site-packages/jinja2/ext.py | 870 -- .../python3.9/site-packages/jinja2/filters.py | 1873 ---- .../site-packages/jinja2/idtracking.py | 318 - .../python3.9/site-packages/jinja2/lexer.py | 868 -- .../python3.9/site-packages/jinja2/loaders.py | 693 -- .../python3.9/site-packages/jinja2/meta.py | 112 - .../site-packages/jinja2/nativetypes.py | 130 - .../python3.9/site-packages/jinja2/nodes.py | 1206 --- .../site-packages/jinja2/optimizer.py | 48 - .../python3.9/site-packages/jinja2/parser.py | 1049 -- .../python3.9/site-packages/jinja2/py.typed | 0 .../python3.9/site-packages/jinja2/runtime.py | 1062 -- .../python3.9/site-packages/jinja2/sandbox.py | 436 - .../python3.9/site-packages/jinja2/tests.py | 256 - .../python3.9/site-packages/jinja2/utils.py | 766 -- .../python3.9/site-packages/jinja2/visitor.py | 92 - .../site-packages/markupsafe/__init__.py | 395 - .../site-packages/markupsafe/_native.py | 8 - .../site-packages/markupsafe/_speedups.c | 204 - .../markupsafe/_speedups.cpython-39-darwin.so | Bin 50688 -> 0 bytes .../site-packages/markupsafe/_speedups.pyi | 1 - .../site-packages/markupsafe/py.typed | 0 .../pip-25.2.dist-info/INSTALLER | 1 - .../site-packages/pip-25.2.dist-info/METADATA | 112 - .../site-packages/pip-25.2.dist-info/RECORD | 860 -- .../pip-25.2.dist-info/REQUESTED | 0 .../site-packages/pip-25.2.dist-info/WHEEL | 5 - .../pip-25.2.dist-info/entry_points.txt | 3 - .../pip-25.2.dist-info/licenses/AUTHORS.txt | 833 -- .../pip-25.2.dist-info/licenses/LICENSE.txt | 20 - .../src/pip/_vendor/cachecontrol/LICENSE.txt | 13 - .../licenses/src/pip/_vendor/certifi/LICENSE | 20 - .../pip/_vendor/dependency_groups/LICENSE.txt | 9 - .../src/pip/_vendor/distlib/LICENSE.txt | 284 - .../licenses/src/pip/_vendor/distro/LICENSE | 202 - .../licenses/src/pip/_vendor/idna/LICENSE.md | 31 - .../licenses/src/pip/_vendor/msgpack/COPYING | 14 - .../src/pip/_vendor/packaging/LICENSE | 3 - .../src/pip/_vendor/packaging/LICENSE.APACHE | 177 - .../src/pip/_vendor/packaging/LICENSE.BSD | 23 - .../src/pip/_vendor/pkg_resources/LICENSE | 17 - .../src/pip/_vendor/platformdirs/LICENSE | 21 - .../licenses/src/pip/_vendor/pygments/LICENSE | 25 - .../src/pip/_vendor/pyproject_hooks/LICENSE | 21 - .../licenses/src/pip/_vendor/requests/LICENSE | 175 - .../src/pip/_vendor/resolvelib/LICENSE | 13 - .../licenses/src/pip/_vendor/rich/LICENSE | 19 - .../licenses/src/pip/_vendor/tomli/LICENSE | 21 - .../src/pip/_vendor/tomli/LICENSE-HEADER | 3 - .../licenses/src/pip/_vendor/tomli_w/LICENSE | 21 - .../src/pip/_vendor/truststore/LICENSE | 21 - .../src/pip/_vendor/urllib3/LICENSE.txt | 21 - .../pip-25.2.dist-info/top_level.txt | 1 - .../python3.9/site-packages/pip/__init__.py | 13 - .../python3.9/site-packages/pip/__main__.py | 24 - .../site-packages/pip/__pip-runner__.py | 50 - .../site-packages/pip/_internal/__init__.py | 18 - .../site-packages/pip/_internal/build_env.py | 349 - .../site-packages/pip/_internal/cache.py | 291 - .../pip/_internal/cli/__init__.py | 3 - .../pip/_internal/cli/autocompletion.py | 184 - .../pip/_internal/cli/base_command.py | 244 - .../pip/_internal/cli/cmdoptions.py | 1138 --- .../pip/_internal/cli/command_context.py | 28 - .../pip/_internal/cli/index_command.py | 175 - .../site-packages/pip/_internal/cli/main.py | 80 - .../pip/_internal/cli/main_parser.py | 134 - .../site-packages/pip/_internal/cli/parser.py | 298 - .../pip/_internal/cli/progress_bars.py | 151 - .../pip/_internal/cli/req_command.py | 351 - .../pip/_internal/cli/spinners.py | 235 - .../pip/_internal/cli/status_codes.py | 6 - .../pip/_internal/commands/__init__.py | 139 - .../pip/_internal/commands/cache.py | 231 - .../pip/_internal/commands/check.py | 66 - .../pip/_internal/commands/completion.py | 135 - .../pip/_internal/commands/configuration.py | 288 - .../pip/_internal/commands/debug.py | 203 - .../pip/_internal/commands/download.py | 145 - .../pip/_internal/commands/freeze.py | 107 - .../pip/_internal/commands/hash.py | 58 - .../pip/_internal/commands/help.py | 40 - .../pip/_internal/commands/index.py | 159 - .../pip/_internal/commands/inspect.py | 92 - .../pip/_internal/commands/install.py | 798 -- .../pip/_internal/commands/list.py | 400 - .../pip/_internal/commands/lock.py | 170 - .../pip/_internal/commands/search.py | 178 - .../pip/_internal/commands/show.py | 231 - .../pip/_internal/commands/uninstall.py | 113 - .../pip/_internal/commands/wheel.py | 181 - .../pip/_internal/configuration.py | 397 - .../pip/_internal/distributions/__init__.py | 21 - .../pip/_internal/distributions/base.py | 55 - .../pip/_internal/distributions/installed.py | 33 - .../pip/_internal/distributions/sdist.py | 165 - .../pip/_internal/distributions/wheel.py | 44 - .../site-packages/pip/_internal/exceptions.py | 881 -- .../pip/_internal/index/__init__.py | 1 - .../pip/_internal/index/collector.py | 489 - .../pip/_internal/index/package_finder.py | 1059 -- .../pip/_internal/index/sources.py | 287 - .../pip/_internal/locations/__init__.py | 441 - .../pip/_internal/locations/_distutils.py | 173 - .../pip/_internal/locations/_sysconfig.py | 215 - .../pip/_internal/locations/base.py | 82 - .../site-packages/pip/_internal/main.py | 12 - .../pip/_internal/metadata/__init__.py | 164 - .../pip/_internal/metadata/_json.py | 87 - .../pip/_internal/metadata/base.py | 685 -- .../_internal/metadata/importlib/__init__.py | 6 - .../_internal/metadata/importlib/_compat.py | 87 - .../_internal/metadata/importlib/_dists.py | 223 - .../pip/_internal/metadata/importlib/_envs.py | 143 - .../pip/_internal/metadata/pkg_resources.py | 298 - .../pip/_internal/models/__init__.py | 1 - .../pip/_internal/models/candidate.py | 25 - .../pip/_internal/models/direct_url.py | 227 - .../pip/_internal/models/format_control.py | 78 - .../pip/_internal/models/index.py | 28 - .../_internal/models/installation_report.py | 57 - .../pip/_internal/models/link.py | 613 -- .../pip/_internal/models/pylock.py | 188 - .../pip/_internal/models/scheme.py | 25 - .../pip/_internal/models/search_scope.py | 126 - .../pip/_internal/models/selection_prefs.py | 53 - .../pip/_internal/models/target_python.py | 122 - .../pip/_internal/models/wheel.py | 141 - .../pip/_internal/network/__init__.py | 1 - .../pip/_internal/network/auth.py | 564 -- .../pip/_internal/network/cache.py | 133 - .../pip/_internal/network/download.py | 342 - .../pip/_internal/network/lazy_wheel.py | 213 - .../pip/_internal/network/session.py | 528 - .../pip/_internal/network/utils.py | 98 - .../pip/_internal/network/xmlrpc.py | 61 - .../pip/_internal/operations/__init__.py | 0 .../_internal/operations/build/__init__.py | 0 .../operations/build/build_tracker.py | 140 - .../_internal/operations/build/metadata.py | 38 - .../operations/build/metadata_editable.py | 41 - .../operations/build/metadata_legacy.py | 73 - .../pip/_internal/operations/build/wheel.py | 38 - .../operations/build/wheel_editable.py | 47 - .../operations/build/wheel_legacy.py | 119 - .../pip/_internal/operations/check.py | 175 - .../pip/_internal/operations/freeze.py | 259 - .../_internal/operations/install/__init__.py | 1 - .../operations/install/editable_legacy.py | 48 - .../pip/_internal/operations/install/wheel.py | 746 -- .../pip/_internal/operations/prepare.py | 742 -- .../site-packages/pip/_internal/pyproject.py | 182 - .../pip/_internal/req/__init__.py | 105 - .../pip/_internal/req/constructors.py | 562 -- .../pip/_internal/req/req_dependency_group.py | 75 - .../pip/_internal/req/req_file.py | 620 -- .../pip/_internal/req/req_install.py | 937 -- .../pip/_internal/req/req_set.py | 81 - .../pip/_internal/req/req_uninstall.py | 639 -- .../pip/_internal/resolution/__init__.py | 0 .../pip/_internal/resolution/base.py | 20 - .../_internal/resolution/legacy/__init__.py | 0 .../_internal/resolution/legacy/resolver.py | 598 -- .../resolution/resolvelib/__init__.py | 0 .../_internal/resolution/resolvelib/base.py | 142 - .../resolution/resolvelib/candidates.py | 582 -- .../resolution/resolvelib/factory.py | 814 -- .../resolution/resolvelib/found_candidates.py | 166 - .../resolution/resolvelib/provider.py | 276 - .../resolution/resolvelib/reporter.py | 85 - .../resolution/resolvelib/requirements.py | 247 - .../resolution/resolvelib/resolver.py | 336 - .../pip/_internal/self_outdated_check.py | 254 - .../pip/_internal/utils/__init__.py | 0 .../pip/_internal/utils/_jaraco_text.py | 109 - .../site-packages/pip/_internal/utils/_log.py | 38 - .../pip/_internal/utils/appdirs.py | 52 - .../pip/_internal/utils/compat.py | 85 - .../pip/_internal/utils/compatibility_tags.py | 201 - .../pip/_internal/utils/datetime.py | 10 - .../pip/_internal/utils/deprecation.py | 126 - .../pip/_internal/utils/direct_url_helpers.py | 87 - .../pip/_internal/utils/egg_link.py | 81 - .../pip/_internal/utils/entrypoints.py | 88 - .../pip/_internal/utils/filesystem.py | 152 - .../pip/_internal/utils/filetypes.py | 24 - .../pip/_internal/utils/glibc.py | 102 - .../pip/_internal/utils/hashes.py | 150 - .../pip/_internal/utils/logging.py | 364 - .../site-packages/pip/_internal/utils/misc.py | 765 -- .../pip/_internal/utils/packaging.py | 44 - .../pip/_internal/utils/retry.py | 45 - .../pip/_internal/utils/setuptools_build.py | 149 - .../pip/_internal/utils/subprocess.py | 248 - .../pip/_internal/utils/temp_dir.py | 294 - .../pip/_internal/utils/unpacking.py | 337 - .../site-packages/pip/_internal/utils/urls.py | 55 - .../pip/_internal/utils/virtualenv.py | 105 - .../pip/_internal/utils/wheel.py | 132 - .../pip/_internal/vcs/__init__.py | 15 - .../site-packages/pip/_internal/vcs/bazaar.py | 130 - .../site-packages/pip/_internal/vcs/git.py | 571 -- .../pip/_internal/vcs/mercurial.py | 186 - .../pip/_internal/vcs/subversion.py | 335 - .../pip/_internal/vcs/versioncontrol.py | 693 -- .../pip/_internal/wheel_builder.py | 334 - .../site-packages/pip/_vendor/__init__.py | 117 - .../pip/_vendor/cachecontrol/__init__.py | 29 - .../pip/_vendor/cachecontrol/_cmd.py | 70 - .../pip/_vendor/cachecontrol/adapter.py | 168 - .../pip/_vendor/cachecontrol/cache.py | 75 - .../_vendor/cachecontrol/caches/__init__.py | 8 - .../_vendor/cachecontrol/caches/file_cache.py | 145 - .../cachecontrol/caches/redis_cache.py | 48 - .../pip/_vendor/cachecontrol/controller.py | 511 - .../pip/_vendor/cachecontrol/filewrapper.py | 119 - .../pip/_vendor/cachecontrol/heuristics.py | 157 - .../pip/_vendor/cachecontrol/py.typed | 0 .../pip/_vendor/cachecontrol/serialize.py | 146 - .../pip/_vendor/cachecontrol/wrapper.py | 43 - .../pip/_vendor/certifi/__init__.py | 4 - .../pip/_vendor/certifi/__main__.py | 12 - .../site-packages/pip/_vendor/certifi/core.py | 83 - .../pip/_vendor/certifi/py.typed | 0 .../pip/_vendor/dependency_groups/__init__.py | 13 - .../pip/_vendor/dependency_groups/__main__.py | 65 - .../dependency_groups/_implementation.py | 209 - .../_lint_dependency_groups.py | 59 - .../_vendor/dependency_groups/_pip_wrapper.py | 62 - .../_vendor/dependency_groups/_toml_compat.py | 9 - .../pip/_vendor/dependency_groups/py.typed | 0 .../pip/_vendor/distlib/__init__.py | 33 - .../pip/_vendor/distlib/compat.py | 1137 --- .../pip/_vendor/distlib/resources.py | 358 - .../pip/_vendor/distlib/scripts.py | 447 - .../site-packages/pip/_vendor/distlib/t32.exe | Bin 97792 -> 0 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 182784 -> 0 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 108032 -> 0 bytes .../site-packages/pip/_vendor/distlib/util.py | 1984 ---- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 91648 -> 0 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 168448 -> 0 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 101888 -> 0 bytes .../pip/_vendor/distro/__init__.py | 54 - .../pip/_vendor/distro/__main__.py | 4 - .../pip/_vendor/distro/distro.py | 1403 --- .../site-packages/pip/_vendor/distro/py.typed | 0 .../pip/_vendor/idna/__init__.py | 45 - .../site-packages/pip/_vendor/idna/codec.py | 122 - .../site-packages/pip/_vendor/idna/compat.py | 15 - .../site-packages/pip/_vendor/idna/core.py | 437 - .../pip/_vendor/idna/idnadata.py | 4243 -------- .../pip/_vendor/idna/intranges.py | 57 - .../pip/_vendor/idna/package_data.py | 1 - .../site-packages/pip/_vendor/idna/py.typed | 0 .../pip/_vendor/idna/uts46data.py | 8681 ----------------- .../pip/_vendor/msgpack/__init__.py | 55 - .../pip/_vendor/msgpack/exceptions.py | 48 - .../site-packages/pip/_vendor/msgpack/ext.py | 170 - .../pip/_vendor/msgpack/fallback.py | 929 -- .../pip/_vendor/packaging/__init__.py | 15 - .../pip/_vendor/packaging/_elffile.py | 109 - .../pip/_vendor/packaging/_manylinux.py | 262 - .../pip/_vendor/packaging/_musllinux.py | 85 - .../pip/_vendor/packaging/_parser.py | 353 - .../pip/_vendor/packaging/_structures.py | 61 - .../pip/_vendor/packaging/_tokenizer.py | 195 - .../_vendor/packaging/licenses/__init__.py | 145 - .../pip/_vendor/packaging/licenses/_spdx.py | 759 -- .../pip/_vendor/packaging/markers.py | 362 - .../pip/_vendor/packaging/metadata.py | 862 -- .../pip/_vendor/packaging/py.typed | 0 .../pip/_vendor/packaging/requirements.py | 91 - .../pip/_vendor/packaging/specifiers.py | 1019 -- .../pip/_vendor/packaging/tags.py | 656 -- .../pip/_vendor/packaging/utils.py | 163 - .../pip/_vendor/packaging/version.py | 582 -- .../pip/_vendor/pkg_resources/__init__.py | 3676 ------- .../pip/_vendor/platformdirs/__init__.py | 631 -- .../pip/_vendor/platformdirs/__main__.py | 55 - .../pip/_vendor/platformdirs/android.py | 249 - .../pip/_vendor/platformdirs/api.py | 299 - .../pip/_vendor/platformdirs/macos.py | 144 - .../pip/_vendor/platformdirs/py.typed | 0 .../pip/_vendor/platformdirs/unix.py | 272 - .../pip/_vendor/platformdirs/version.py | 21 - .../pip/_vendor/platformdirs/windows.py | 272 - .../pip/_vendor/pygments/__init__.py | 82 - .../pip/_vendor/pygments/__main__.py | 17 - .../pip/_vendor/pygments/console.py | 70 - .../pip/_vendor/pygments/filter.py | 70 - .../pip/_vendor/pygments/filters/__init__.py | 940 -- .../pip/_vendor/pygments/formatter.py | 129 - .../_vendor/pygments/formatters/__init__.py | 157 - .../_vendor/pygments/formatters/_mapping.py | 23 - .../pip/_vendor/pygments/lexer.py | 963 -- .../pip/_vendor/pygments/lexers/__init__.py | 362 - .../pip/_vendor/pygments/lexers/_mapping.py | 602 -- .../pip/_vendor/pygments/lexers/python.py | 1201 --- .../pip/_vendor/pygments/modeline.py | 43 - .../pip/_vendor/pygments/plugin.py | 72 - .../pip/_vendor/pygments/regexopt.py | 91 - .../pip/_vendor/pygments/scanner.py | 104 - .../pip/_vendor/pygments/sphinxext.py | 247 - .../pip/_vendor/pygments/style.py | 203 - .../pip/_vendor/pygments/styles/__init__.py | 61 - .../pip/_vendor/pygments/styles/_mapping.py | 54 - .../pip/_vendor/pygments/token.py | 214 - .../pip/_vendor/pygments/unistring.py | 153 - .../pip/_vendor/pygments/util.py | 324 - .../pip/_vendor/pyproject_hooks/__init__.py | 31 - .../pip/_vendor/pyproject_hooks/_impl.py | 410 - .../pyproject_hooks/_in_process/__init__.py | 21 - .../_in_process/_in_process.py | 389 - .../pip/_vendor/pyproject_hooks/py.typed | 0 .../pip/_vendor/requests/__init__.py | 179 - .../pip/_vendor/requests/__version__.py | 14 - .../pip/_vendor/requests/_internal_utils.py | 50 - .../pip/_vendor/requests/adapters.py | 719 -- .../site-packages/pip/_vendor/requests/api.py | 157 - .../pip/_vendor/requests/auth.py | 314 - .../pip/_vendor/requests/certs.py | 17 - .../pip/_vendor/requests/compat.py | 90 - .../pip/_vendor/requests/cookies.py | 561 -- .../pip/_vendor/requests/exceptions.py | 151 - .../pip/_vendor/requests/help.py | 127 - .../pip/_vendor/requests/hooks.py | 33 - .../pip/_vendor/requests/models.py | 1039 -- .../pip/_vendor/requests/packages.py | 25 - .../pip/_vendor/requests/sessions.py | 831 -- .../pip/_vendor/requests/status_codes.py | 128 - .../pip/_vendor/requests/structures.py | 99 - .../pip/_vendor/requests/utils.py | 1086 --- .../pip/_vendor/resolvelib/__init__.py | 27 - .../pip/_vendor/resolvelib/providers.py | 196 - .../pip/_vendor/resolvelib/py.typed | 0 .../pip/_vendor/resolvelib/reporters.py | 55 - .../_vendor/resolvelib/resolvers/__init__.py | 27 - .../_vendor/resolvelib/resolvers/abstract.py | 47 - .../_vendor/resolvelib/resolvers/criterion.py | 48 - .../resolvelib/resolvers/exceptions.py | 57 - .../resolvelib/resolvers/resolution.py | 622 -- .../pip/_vendor/resolvelib/structs.py | 209 - .../pip/_vendor/rich/__init__.py | 177 - .../pip/_vendor/rich/__main__.py | 245 - .../pip/_vendor/rich/_cell_widths.py | 454 - .../pip/_vendor/rich/_emoji_codes.py | 3610 ------- .../pip/_vendor/rich/_emoji_replace.py | 32 - .../pip/_vendor/rich/_export_format.py | 76 - .../pip/_vendor/rich/_extension.py | 10 - .../site-packages/pip/_vendor/rich/_fileno.py | 24 - .../pip/_vendor/rich/_inspect.py | 268 - .../pip/_vendor/rich/_log_render.py | 94 - .../site-packages/pip/_vendor/rich/_loop.py | 43 - .../pip/_vendor/rich/_null_file.py | 69 - .../pip/_vendor/rich/_palettes.py | 309 - .../site-packages/pip/_vendor/rich/_pick.py | 17 - .../site-packages/pip/_vendor/rich/_ratio.py | 153 - .../pip/_vendor/rich/_spinners.py | 482 - .../site-packages/pip/_vendor/rich/_stack.py | 16 - .../site-packages/pip/_vendor/rich/_timer.py | 19 - .../pip/_vendor/rich/_win32_console.py | 661 -- .../pip/_vendor/rich/_windows.py | 71 - .../pip/_vendor/rich/_windows_renderer.py | 56 - .../site-packages/pip/_vendor/rich/_wrap.py | 93 - .../site-packages/pip/_vendor/rich/abc.py | 33 - .../site-packages/pip/_vendor/rich/align.py | 306 - .../site-packages/pip/_vendor/rich/ansi.py | 241 - .../site-packages/pip/_vendor/rich/bar.py | 93 - .../site-packages/pip/_vendor/rich/box.py | 474 - .../site-packages/pip/_vendor/rich/cells.py | 174 - .../site-packages/pip/_vendor/rich/color.py | 621 -- .../pip/_vendor/rich/color_triplet.py | 38 - .../site-packages/pip/_vendor/rich/columns.py | 187 - .../site-packages/pip/_vendor/rich/console.py | 2680 ----- .../pip/_vendor/rich/constrain.py | 37 - .../pip/_vendor/rich/containers.py | 167 - .../site-packages/pip/_vendor/rich/control.py | 219 - .../pip/_vendor/rich/default_styles.py | 193 - .../pip/_vendor/rich/diagnose.py | 39 - .../site-packages/pip/_vendor/rich/emoji.py | 91 - .../site-packages/pip/_vendor/rich/errors.py | 34 - .../pip/_vendor/rich/file_proxy.py | 57 - .../pip/_vendor/rich/filesize.py | 88 - .../pip/_vendor/rich/highlighter.py | 232 - .../site-packages/pip/_vendor/rich/json.py | 139 - .../site-packages/pip/_vendor/rich/jupyter.py | 101 - .../site-packages/pip/_vendor/rich/layout.py | 442 - .../site-packages/pip/_vendor/rich/live.py | 400 - .../pip/_vendor/rich/live_render.py | 106 - .../site-packages/pip/_vendor/rich/logging.py | 297 - .../site-packages/pip/_vendor/rich/markup.py | 251 - .../site-packages/pip/_vendor/rich/measure.py | 151 - .../site-packages/pip/_vendor/rich/padding.py | 141 - .../site-packages/pip/_vendor/rich/pager.py | 34 - .../site-packages/pip/_vendor/rich/palette.py | 100 - .../site-packages/pip/_vendor/rich/panel.py | 317 - .../site-packages/pip/_vendor/rich/pretty.py | 1016 -- .../pip/_vendor/rich/progress.py | 1715 ---- .../pip/_vendor/rich/progress_bar.py | 223 - .../site-packages/pip/_vendor/rich/prompt.py | 400 - .../pip/_vendor/rich/protocol.py | 42 - .../site-packages/pip/_vendor/rich/py.typed | 0 .../site-packages/pip/_vendor/rich/region.py | 10 - .../site-packages/pip/_vendor/rich/repr.py | 149 - .../site-packages/pip/_vendor/rich/rule.py | 130 - .../site-packages/pip/_vendor/rich/scope.py | 86 - .../site-packages/pip/_vendor/rich/screen.py | 54 - .../site-packages/pip/_vendor/rich/segment.py | 752 -- .../site-packages/pip/_vendor/rich/spinner.py | 132 - .../site-packages/pip/_vendor/rich/status.py | 131 - .../site-packages/pip/_vendor/rich/style.py | 796 -- .../site-packages/pip/_vendor/rich/styled.py | 42 - .../site-packages/pip/_vendor/rich/syntax.py | 985 -- .../site-packages/pip/_vendor/rich/table.py | 1006 -- .../pip/_vendor/rich/terminal_theme.py | 153 - .../site-packages/pip/_vendor/rich/text.py | 1361 --- .../site-packages/pip/_vendor/rich/theme.py | 115 - .../site-packages/pip/_vendor/rich/themes.py | 5 - .../pip/_vendor/rich/traceback.py | 899 -- .../site-packages/pip/_vendor/rich/tree.py | 257 - .../pip/_vendor/tomli/__init__.py | 8 - .../pip/_vendor/tomli/_parser.py | 770 -- .../site-packages/pip/_vendor/tomli/_re.py | 112 - .../site-packages/pip/_vendor/tomli/_types.py | 10 - .../site-packages/pip/_vendor/tomli/py.typed | 1 - .../pip/_vendor/tomli_w/__init__.py | 4 - .../pip/_vendor/tomli_w/_writer.py | 229 - .../pip/_vendor/tomli_w/py.typed | 1 - .../pip/_vendor/truststore/__init__.py | 36 - .../pip/_vendor/truststore/_api.py | 333 - .../pip/_vendor/truststore/_macos.py | 571 -- .../pip/_vendor/truststore/_openssl.py | 66 - .../pip/_vendor/truststore/_ssl_constants.py | 31 - .../pip/_vendor/truststore/_windows.py | 567 -- .../pip/_vendor/truststore/py.typed | 0 .../pip/_vendor/urllib3/__init__.py | 102 - .../pip/_vendor/urllib3/_collections.py | 355 - .../pip/_vendor/urllib3/_version.py | 2 - .../pip/_vendor/urllib3/connection.py | 572 -- .../pip/_vendor/urllib3/connectionpool.py | 1140 --- .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../urllib3/contrib/_appengine_environ.py | 36 - .../contrib/_securetransport/__init__.py | 0 .../contrib/_securetransport/bindings.py | 519 - .../contrib/_securetransport/low_level.py | 397 - .../pip/_vendor/urllib3/contrib/appengine.py | 314 - .../pip/_vendor/urllib3/contrib/ntlmpool.py | 130 - .../pip/_vendor/urllib3/contrib/pyopenssl.py | 518 - .../urllib3/contrib/securetransport.py | 920 -- .../pip/_vendor/urllib3/contrib/socks.py | 216 - .../pip/_vendor/urllib3/exceptions.py | 323 - .../pip/_vendor/urllib3/fields.py | 274 - .../pip/_vendor/urllib3/filepost.py | 98 - .../pip/_vendor/urllib3/packages/__init__.py | 0 .../urllib3/packages/backports/__init__.py | 0 .../urllib3/packages/backports/makefile.py | 51 - .../packages/backports/weakref_finalize.py | 155 - .../pip/_vendor/urllib3/packages/six.py | 1076 -- .../pip/_vendor/urllib3/poolmanager.py | 540 - .../pip/_vendor/urllib3/request.py | 191 - .../pip/_vendor/urllib3/response.py | 879 -- .../pip/_vendor/urllib3/util/__init__.py | 49 - .../pip/_vendor/urllib3/util/connection.py | 149 - .../pip/_vendor/urllib3/util/proxy.py | 57 - .../pip/_vendor/urllib3/util/queue.py | 22 - .../pip/_vendor/urllib3/util/request.py | 137 - .../pip/_vendor/urllib3/util/response.py | 107 - .../pip/_vendor/urllib3/util/retry.py | 622 -- .../pip/_vendor/urllib3/util/ssl_.py | 504 - .../urllib3/util/ssl_match_hostname.py | 159 - .../pip/_vendor/urllib3/util/ssltransport.py | 221 - .../pip/_vendor/urllib3/util/timeout.py | 271 - .../pip/_vendor/urllib3/util/url.py | 435 - .../pip/_vendor/urllib3/util/wait.py | 152 - .../site-packages/pip/_vendor/vendor.txt | 19 - .../lib/python3.9/site-packages/pip/py.typed | 4 - .../site-packages/pkg_resources/__init__.py | 3288 ------- .../pkg_resources/_vendor/__init__.py | 0 .../pkg_resources/_vendor/appdirs.py | 608 -- .../_vendor/packaging/__about__.py | 27 - .../_vendor/packaging/__init__.py | 26 - .../_vendor/packaging/_compat.py | 38 - .../_vendor/packaging/_structures.py | 86 - .../_vendor/packaging/_typing.py | 48 - .../_vendor/packaging/markers.py | 328 - .../_vendor/packaging/requirements.py | 145 - .../_vendor/packaging/specifiers.py | 863 -- .../pkg_resources/_vendor/packaging/tags.py | 751 -- .../pkg_resources/_vendor/packaging/utils.py | 65 - .../_vendor/packaging/version.py | 535 - .../pkg_resources/_vendor/pyparsing.py | 5742 ----------- .../pkg_resources/extern/__init__.py | 73 - .../data/my-test-package-source/setup.py | 6 - .../priority-2.0.0.dist-info/INSTALLER | 1 - .../priority-2.0.0.dist-info/LICENSE | 19 - .../priority-2.0.0.dist-info/METADATA | 164 - .../priority-2.0.0.dist-info/RECORD | 11 - .../priority-2.0.0.dist-info/WHEEL | 5 - .../priority-2.0.0.dist-info/top_level.txt | 1 - .../site-packages/priority/__init__.py | 19 - .../site-packages/priority/priority.py | 502 - .../python3.9/site-packages/priority/py.typed | 0 .../quart-0.20.0.dist-info/INSTALLER | 1 - .../quart-0.20.0.dist-info/METADATA | 128 - .../quart-0.20.0.dist-info/RECORD | 76 - .../quart-0.20.0.dist-info/REQUESTED | 0 .../quart-0.20.0.dist-info/WHEEL | 4 - .../quart-0.20.0.dist-info/entry_points.txt | 3 - .../python3.9/site-packages/quart/__init__.py | 55 - .../python3.9/site-packages/quart/__main__.py | 6 - .../lib/python3.9/site-packages/quart/app.py | 1828 ---- .../lib/python3.9/site-packages/quart/asgi.py | 408 - .../site-packages/quart/blueprints.py | 415 - .../lib/python3.9/site-packages/quart/cli.py | 780 -- .../python3.9/site-packages/quart/config.py | 38 - .../lib/python3.9/site-packages/quart/ctx.py | 483 - .../site-packages/quart/datastructures.py | 46 - .../python3.9/site-packages/quart/debug.py | 114 - .../site-packages/quart/formparser.py | 246 - .../python3.9/site-packages/quart/globals.py | 59 - .../python3.9/site-packages/quart/helpers.py | 403 - .../site-packages/quart/json/__init__.py | 47 - .../site-packages/quart/json/provider.py | 2 - .../python3.9/site-packages/quart/json/tag.py | 10 - .../python3.9/site-packages/quart/logging.py | 80 - .../python3.9/site-packages/quart/py.typed | 1 - .../python3.9/site-packages/quart/routing.py | 92 - .../python3.9/site-packages/quart/sessions.py | 238 - .../python3.9/site-packages/quart/signals.py | 80 - .../site-packages/quart/templating.py | 157 - .../site-packages/quart/testing/__init__.py | 47 - .../site-packages/quart/testing/app.py | 84 - .../site-packages/quart/testing/client.py | 457 - .../quart/testing/connections.py | 200 - .../site-packages/quart/testing/utils.py | 229 - .../python3.9/site-packages/quart/typing.py | 333 - .../python3.9/site-packages/quart/utils.py | 186 - .../python3.9/site-packages/quart/views.py | 134 - .../site-packages/quart/wrappers/__init__.py | 15 - .../site-packages/quart/wrappers/base.py | 119 - .../site-packages/quart/wrappers/request.py | 414 - .../site-packages/quart/wrappers/response.py | 500 - .../site-packages/quart/wrappers/websocket.py | 104 - .../setuptools-58.0.4.dist-info/INSTALLER | 1 - .../setuptools-58.0.4.dist-info/LICENSE | 19 - .../setuptools-58.0.4.dist-info/METADATA | 119 - .../setuptools-58.0.4.dist-info/RECORD | 296 - .../setuptools-58.0.4.dist-info/REQUESTED | 0 .../setuptools-58.0.4.dist-info/WHEEL | 5 - .../entry_points.txt | 56 - .../setuptools-58.0.4.dist-info/top_level.txt | 3 - .../site-packages/setuptools/__init__.py | 242 - .../setuptools/_deprecation_warning.py | 7 - .../setuptools/_distutils/__init__.py | 15 - .../setuptools/_distutils/_msvccompiler.py | 561 -- .../setuptools/_distutils/archive_util.py | 256 - .../setuptools/_distutils/bcppcompiler.py | 393 - .../setuptools/_distutils/ccompiler.py | 1123 --- .../setuptools/_distutils/cmd.py | 403 - .../setuptools/_distutils/command/__init__.py | 31 - .../setuptools/_distutils/command/bdist.py | 143 - .../_distutils/command/bdist_dumb.py | 123 - .../_distutils/command/bdist_msi.py | 749 -- .../_distutils/command/bdist_rpm.py | 579 -- .../_distutils/command/bdist_wininst.py | 377 - .../setuptools/_distutils/command/build.py | 157 - .../_distutils/command/build_clib.py | 209 - .../_distutils/command/build_ext.py | 757 -- .../setuptools/_distutils/command/build_py.py | 392 - .../_distutils/command/build_scripts.py | 152 - .../setuptools/_distutils/command/check.py | 148 - .../setuptools/_distutils/command/clean.py | 76 - .../setuptools/_distutils/command/config.py | 344 - .../setuptools/_distutils/command/install.py | 677 -- .../_distutils/command/install_data.py | 79 - .../_distutils/command/install_egg_info.py | 77 - .../_distutils/command/install_headers.py | 47 - .../_distutils/command/install_lib.py | 217 - .../_distutils/command/install_scripts.py | 60 - .../_distutils/command/py37compat.py | 30 - .../setuptools/_distutils/command/register.py | 304 - .../setuptools/_distutils/command/sdist.py | 494 - .../setuptools/_distutils/command/upload.py | 214 - .../setuptools/_distutils/config.py | 130 - .../setuptools/_distutils/core.py | 234 - .../setuptools/_distutils/cygwinccompiler.py | 414 - .../setuptools/_distutils/debug.py | 5 - .../setuptools/_distutils/dep_util.py | 92 - .../setuptools/_distutils/dir_util.py | 210 - .../setuptools/_distutils/dist.py | 1257 --- .../setuptools/_distutils/errors.py | 97 - .../setuptools/_distutils/extension.py | 240 - .../setuptools/_distutils/fancy_getopt.py | 457 - .../setuptools/_distutils/file_util.py | 238 - .../setuptools/_distutils/filelist.py | 355 - .../setuptools/_distutils/log.py | 77 - .../setuptools/_distutils/msvc9compiler.py | 788 -- .../setuptools/_distutils/msvccompiler.py | 643 -- .../setuptools/_distutils/py35compat.py | 19 - .../setuptools/_distutils/py38compat.py | 7 - .../setuptools/_distutils/spawn.py | 106 - .../setuptools/_distutils/sysconfig.py | 573 -- .../setuptools/_distutils/text_file.py | 286 - .../setuptools/_distutils/unixccompiler.py | 332 - .../setuptools/_distutils/util.py | 535 - .../setuptools/_distutils/version.py | 347 - .../setuptools/_distutils/versionpredicate.py | 166 - .../site-packages/setuptools/_imp.py | 82 - .../setuptools/_vendor/__init__.py | 0 .../_vendor/more_itertools/__init__.py | 4 - .../setuptools/_vendor/more_itertools/more.py | 3825 -------- .../_vendor/more_itertools/recipes.py | 620 -- .../setuptools/_vendor/ordered_set.py | 488 - .../setuptools/_vendor/packaging/__about__.py | 27 - .../setuptools/_vendor/packaging/__init__.py | 26 - .../setuptools/_vendor/packaging/_compat.py | 38 - .../_vendor/packaging/_structures.py | 86 - .../setuptools/_vendor/packaging/_typing.py | 48 - .../setuptools/_vendor/packaging/markers.py | 328 - .../_vendor/packaging/requirements.py | 145 - .../_vendor/packaging/specifiers.py | 863 -- .../setuptools/_vendor/packaging/tags.py | 751 -- .../setuptools/_vendor/packaging/utils.py | 65 - .../setuptools/_vendor/packaging/version.py | 535 - .../setuptools/_vendor/pyparsing.py | 5742 ----------- .../site-packages/setuptools/archive_util.py | 205 - .../site-packages/setuptools/build_meta.py | 281 - .../site-packages/setuptools/cli-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/cli-64.exe | Bin 74752 -> 0 bytes .../site-packages/setuptools/cli.exe | Bin 65536 -> 0 bytes .../setuptools/command/__init__.py | 8 - .../site-packages/setuptools/command/alias.py | 78 - .../setuptools/command/bdist_egg.py | 456 - .../setuptools/command/bdist_rpm.py | 31 - .../setuptools/command/build_clib.py | 101 - .../setuptools/command/build_ext.py | 328 - .../setuptools/command/build_py.py | 232 - .../setuptools/command/develop.py | 193 - .../setuptools/command/dist_info.py | 36 - .../setuptools/command/easy_install.py | 2290 ----- .../setuptools/command/egg_info.py | 734 -- .../setuptools/command/install.py | 125 - .../setuptools/command/install_egg_info.py | 62 - .../setuptools/command/install_lib.py | 122 - .../setuptools/command/install_scripts.py | 69 - .../setuptools/command/launcher manifest.xml | 15 - .../setuptools/command/py36compat.py | 134 - .../setuptools/command/register.py | 18 - .../setuptools/command/rotate.py | 64 - .../setuptools/command/saveopts.py | 22 - .../site-packages/setuptools/command/sdist.py | 189 - .../setuptools/command/setopt.py | 149 - .../site-packages/setuptools/command/test.py | 252 - .../setuptools/command/upload.py | 17 - .../setuptools/command/upload_docs.py | 202 - .../site-packages/setuptools/config.py | 749 -- .../site-packages/setuptools/dep_util.py | 25 - .../site-packages/setuptools/depends.py | 175 - .../site-packages/setuptools/dist.py | 1150 --- .../site-packages/setuptools/errors.py | 16 - .../site-packages/setuptools/extension.py | 55 - .../setuptools/extern/__init__.py | 73 - .../site-packages/setuptools/glob.py | 167 - .../site-packages/setuptools/gui-32.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/gui-64.exe | Bin 75264 -> 0 bytes .../site-packages/setuptools/gui.exe | Bin 65536 -> 0 bytes .../site-packages/setuptools/installer.py | 97 - .../site-packages/setuptools/launch.py | 36 - .../site-packages/setuptools/monkey.py | 177 - .../site-packages/setuptools/msvc.py | 1805 ---- .../site-packages/setuptools/namespaces.py | 107 - .../site-packages/setuptools/package_index.py | 1119 --- .../site-packages/setuptools/py34compat.py | 13 - .../site-packages/setuptools/sandbox.py | 530 - .../setuptools/script (dev).tmpl | 6 - .../site-packages/setuptools/script.tmpl | 3 - .../site-packages/setuptools/unicode_utils.py | 42 - .../site-packages/setuptools/version.py | 6 - .../site-packages/setuptools/wheel.py | 213 - .../setuptools/windows_support.py | 29 - .../taskgroup-0.2.2.dist-info/INSTALLER | 1 - .../taskgroup-0.2.2.dist-info/LICENSE | 21 - .../taskgroup-0.2.2.dist-info/METADATA | 114 - .../taskgroup-0.2.2.dist-info/RECORD | 18 - .../taskgroup-0.2.2.dist-info/WHEEL | 5 - .../site-packages/taskgroup/__init__.py | 11 - .../site-packages/taskgroup/install.py | 128 - .../site-packages/taskgroup/py.typed | 0 .../site-packages/taskgroup/runners.py | 254 - .../site-packages/taskgroup/taskgroups.py | 381 - .../site-packages/taskgroup/tasks.py | 114 - .../site-packages/taskgroup/timeouts.py | 201 - .../tomli-2.2.1.dist-info/INSTALLER | 1 - .../tomli-2.2.1.dist-info/LICENSE | 21 - .../tomli-2.2.1.dist-info/METADATA | 268 - .../tomli-2.2.1.dist-info/RECORD | 14 - .../site-packages/tomli-2.2.1.dist-info/WHEEL | 4 - .../python3.9/site-packages/tomli/__init__.py | 8 - .../python3.9/site-packages/tomli/_parser.py | 770 -- .../lib/python3.9/site-packages/tomli/_re.py | 112 - .../python3.9/site-packages/tomli/_types.py | 10 - .../python3.9/site-packages/tomli/py.typed | 1 - .../INSTALLER | 1 - .../METADATA | 68 - .../typing_extensions-4.14.1.dist-info/RECORD | 7 - .../typing_extensions-4.14.1.dist-info/WHEEL | 4 - .../licenses/LICENSE | 279 - .../site-packages/typing_extensions.py | 4244 -------- .../werkzeug-3.1.3.dist-info/INSTALLER | 1 - .../werkzeug-3.1.3.dist-info/LICENSE.txt | 28 - .../werkzeug-3.1.3.dist-info/METADATA | 99 - .../werkzeug-3.1.3.dist-info/RECORD | 116 - .../werkzeug-3.1.3.dist-info/WHEEL | 4 - .../site-packages/werkzeug/__init__.py | 4 - .../site-packages/werkzeug/_internal.py | 211 - .../site-packages/werkzeug/_reloader.py | 471 - .../werkzeug/datastructures/__init__.py | 64 - .../werkzeug/datastructures/accept.py | 350 - .../werkzeug/datastructures/auth.py | 317 - .../werkzeug/datastructures/cache_control.py | 273 - .../werkzeug/datastructures/csp.py | 100 - .../werkzeug/datastructures/etag.py | 106 - .../werkzeug/datastructures/file_storage.py | 209 - .../werkzeug/datastructures/headers.py | 662 -- .../werkzeug/datastructures/mixins.py | 317 - .../werkzeug/datastructures/range.py | 214 - .../werkzeug/datastructures/structures.py | 1239 --- .../site-packages/werkzeug/debug/__init__.py | 565 -- .../site-packages/werkzeug/debug/console.py | 219 - .../site-packages/werkzeug/debug/repr.py | 282 - .../werkzeug/debug/shared/ICON_LICENSE.md | 6 - .../werkzeug/debug/shared/console.png | Bin 507 -> 0 bytes .../werkzeug/debug/shared/debugger.js | 344 - .../werkzeug/debug/shared/less.png | Bin 191 -> 0 bytes .../werkzeug/debug/shared/more.png | Bin 200 -> 0 bytes .../werkzeug/debug/shared/style.css | 150 - .../site-packages/werkzeug/debug/tbtools.py | 450 - .../site-packages/werkzeug/exceptions.py | 894 -- .../site-packages/werkzeug/formparser.py | 430 - .../python3.9/site-packages/werkzeug/http.py | 1405 --- .../python3.9/site-packages/werkzeug/local.py | 653 -- .../werkzeug/middleware/__init__.py | 0 .../werkzeug/middleware/dispatcher.py | 81 - .../werkzeug/middleware/http_proxy.py | 236 - .../site-packages/werkzeug/middleware/lint.py | 439 - .../werkzeug/middleware/profiler.py | 155 - .../werkzeug/middleware/proxy_fix.py | 183 - .../werkzeug/middleware/shared_data.py | 283 - .../python3.9/site-packages/werkzeug/py.typed | 0 .../werkzeug/routing/__init__.py | 134 - .../werkzeug/routing/converters.py | 261 - .../werkzeug/routing/exceptions.py | 152 - .../site-packages/werkzeug/routing/map.py | 951 -- .../site-packages/werkzeug/routing/matcher.py | 202 - .../site-packages/werkzeug/routing/rules.py | 928 -- .../site-packages/werkzeug/sansio/__init__.py | 0 .../site-packages/werkzeug/sansio/http.py | 170 - .../werkzeug/sansio/multipart.py | 323 - .../site-packages/werkzeug/sansio/request.py | 534 - .../site-packages/werkzeug/sansio/response.py | 763 -- .../site-packages/werkzeug/sansio/utils.py | 167 - .../site-packages/werkzeug/security.py | 166 - .../site-packages/werkzeug/serving.py | 1125 --- .../python3.9/site-packages/werkzeug/test.py | 1464 --- .../site-packages/werkzeug/testapp.py | 194 - .../python3.9/site-packages/werkzeug/urls.py | 203 - .../site-packages/werkzeug/user_agent.py | 47 - .../python3.9/site-packages/werkzeug/utils.py | 691 -- .../werkzeug/wrappers/__init__.py | 3 - .../werkzeug/wrappers/request.py | 650 -- .../werkzeug/wrappers/response.py | 831 -- .../python3.9/site-packages/werkzeug/wsgi.py | 595 -- .../wsproto-1.2.0.dist-info/INSTALLER | 1 - .../wsproto-1.2.0.dist-info/LICENSE | 21 - .../wsproto-1.2.0.dist-info/METADATA | 177 - .../wsproto-1.2.0.dist-info/RECORD | 23 - .../wsproto-1.2.0.dist-info/WHEEL | 5 - .../wsproto-1.2.0.dist-info/top_level.txt | 1 - .../site-packages/wsproto/__init__.py | 94 - .../site-packages/wsproto/connection.py | 189 - .../python3.9/site-packages/wsproto/events.py | 295 - .../site-packages/wsproto/extensions.py | 315 - .../site-packages/wsproto/frame_protocol.py | 673 -- .../site-packages/wsproto/handshake.py | 491 - .../python3.9/site-packages/wsproto/py.typed | 1 - .../python3.9/site-packages/wsproto/typing.py | 3 - .../site-packages/wsproto/utilities.py | 88 - .../zipp-3.23.0.dist-info/INSTALLER | 1 - .../zipp-3.23.0.dist-info/METADATA | 106 - .../zipp-3.23.0.dist-info/RECORD | 20 - .../site-packages/zipp-3.23.0.dist-info/WHEEL | 5 - .../zipp-3.23.0.dist-info/licenses/LICENSE | 18 - .../zipp-3.23.0.dist-info/top_level.txt | 1 - .../python3.9/site-packages/zipp/__init__.py | 456 - .../site-packages/zipp/_functools.py | 20 - .../site-packages/zipp/compat/__init__.py | 0 .../site-packages/zipp/compat/overlay.py | 37 - .../site-packages/zipp/compat/py310.py | 13 - .../site-packages/zipp/compat/py313.py | 34 - .../lib/python3.9/site-packages/zipp/glob.py | 116 - serverenv/pyvenv.cfg | 3 - 1072 files changed, 287351 deletions(-) delete mode 100644 serverenv/bin/Activate.ps1 delete mode 100644 serverenv/bin/activate delete mode 100644 serverenv/bin/activate.csh delete mode 100644 serverenv/bin/activate.fish delete mode 100755 serverenv/bin/flask delete mode 100755 serverenv/bin/hypercorn delete mode 100755 serverenv/bin/pip delete mode 100755 serverenv/bin/pip3 delete mode 100755 serverenv/bin/pip3.9 delete mode 120000 serverenv/bin/python delete mode 120000 serverenv/bin/python3 delete mode 120000 serverenv/bin/python3.9 delete mode 100755 serverenv/bin/quart delete mode 100644 serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/_distutils_hack/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/_distutils_hack/override.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/NOTICE delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/os.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/ospath.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/tempfile/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/tempfile/temptypes.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/threadpool/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/threadpool/binary.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/threadpool/text.py delete mode 100644 serverenv/lib/python3.9/site-packages/aiofiles/threadpool/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/blinker/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/blinker/_utilities.py delete mode 100644 serverenv/lib/python3.9/site-packages/blinker/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/blinker/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/click/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/_compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/_termui_impl.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/_textwrap.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/_winconsole.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/core.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/decorators.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/formatting.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/globals.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/parser.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/click/shell_completion.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/termui.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/testing.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/types.py delete mode 100644 serverenv/lib/python3.9/site-packages/click/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/distutils-precedence.pth delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/licenses/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup/_catch.py delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup/_exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup/_formatting.py delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup/_suppress.py delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup/_version.py delete mode 100644 serverenv/lib/python3.9/site-packages/exceptiongroup/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/entry_points.txt delete mode 100644 serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/licenses/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/flask/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/app.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/blueprints.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/cli.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/config.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/ctx.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/debughelpers.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/globals.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/helpers.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/json/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/json/provider.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/json/tag.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/logging.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/flask/sansio/README.md delete mode 100644 serverenv/lib/python3.9/site-packages/flask/sansio/app.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/sansio/blueprints.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/sansio/scaffold.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/sessions.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/signals.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/templating.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/testing.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/typing.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/views.py delete mode 100644 serverenv/lib/python3.9/site-packages/flask/wrappers.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/h11/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_abnf.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_connection.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_events.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_headers.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_readers.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_receivebuffer.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_state.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_util.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_version.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/_writers.py delete mode 100644 serverenv/lib/python3.9/site-packages/h11/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/h2/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/config.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/connection.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/errors.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/events.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/frame_buffer.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/h2/settings.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/stream.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/utilities.py delete mode 100644 serverenv/lib/python3.9/site-packages/h2/windows.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/hpack.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/huffman.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/huffman_constants.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/huffman_table.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/struct.py delete mode 100644 serverenv/lib/python3.9/site-packages/hpack/table.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/entry_points.txt delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/app_wrappers.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/lifespan.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/run.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/statsd.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/task_group.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/tcp_server.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/udp_server.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/asyncio/worker_context.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/config.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/events.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/logging.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/middleware/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/middleware/dispatcher.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/middleware/http_to_https.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/middleware/proxy_fix.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/middleware/wsgi.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/events.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/h11.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/h2.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/h3.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/http_stream.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/quic.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/protocol/ws_stream.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/run.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/statsd.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/lifespan.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/run.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/statsd.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/task_group.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/tcp_server.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/udp_server.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/trio/worker_context.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/typing.py delete mode 100644 serverenv/lib/python3.9/site-packages/hypercorn/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe/flags.py delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe/frame.py delete mode 100644 serverenv/lib/python3.9/site-packages/hyperframe/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/licenses/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_adapters.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_collections.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_functools.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_itertools.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_meta.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_text.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/_typing.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/compat/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py311.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py39.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/diagnose.py delete mode 100644 serverenv/lib/python3.9/site-packages/importlib_metadata/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/_json.py delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/encoding.py delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/exc.py delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/serializer.py delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/signer.py delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/timed.py delete mode 100644 serverenv/lib/python3.9/site-packages/itsdangerous/url_safe.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/entry_points.txt delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/_identifier.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/async_utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/bccache.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/compiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/constants.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/debug.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/defaults.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/environment.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/ext.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/filters.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/idtracking.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/lexer.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/loaders.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/meta.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/nativetypes.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/nodes.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/optimizer.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/parser.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/runtime.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/sandbox.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/tests.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/jinja2/visitor.py delete mode 100644 serverenv/lib/python3.9/site-packages/markupsafe/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/markupsafe/_native.py delete mode 100644 serverenv/lib/python3.9/site-packages/markupsafe/_speedups.c delete mode 100755 serverenv/lib/python3.9/site-packages/markupsafe/_speedups.cpython-39-darwin.so delete mode 100644 serverenv/lib/python3.9/site-packages/markupsafe/_speedups.pyi delete mode 100644 serverenv/lib/python3.9/site-packages/markupsafe/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/REQUESTED delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/entry_points.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/AUTHORS.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/certifi/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/distro/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/msgpack/COPYING delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/pygments/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/requests/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/rich/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/truststore/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip-25.2.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/__pip-runner__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/build_env.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cache.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/autocompletion.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/base_command.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/cmdoptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/command_context.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/index_command.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/main.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/main_parser.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/parser.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/progress_bars.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/req_command.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/spinners.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/cli/status_codes.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/cache.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/check.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/completion.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/configuration.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/debug.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/download.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/freeze.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/hash.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/help.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/index.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/inspect.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/install.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/list.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/lock.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/search.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/show.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/uninstall.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/commands/wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/configuration.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/distributions/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/distributions/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/distributions/installed.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/distributions/sdist.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/distributions/wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/index/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/index/collector.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/index/package_finder.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/index/sources.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/locations/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/locations/_distutils.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/locations/_sysconfig.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/locations/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/main.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/_json.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/importlib/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/importlib/_compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/importlib/_dists.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/importlib/_envs.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/metadata/pkg_resources.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/candidate.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/direct_url.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/format_control.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/index.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/installation_report.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/link.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/pylock.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/scheme.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/search_scope.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/selection_prefs.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/target_python.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/models/wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/auth.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/cache.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/download.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/lazy_wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/session.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/network/xmlrpc.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/build_tracker.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata_editable.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/metadata_legacy.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel_editable.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel_legacy.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/check.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/freeze.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/install/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/install/editable_legacy.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/install/wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/operations/prepare.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/pyproject.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/req/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/req/constructors.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/req/req_dependency_group.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/req/req_file.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/req/req_install.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/req/req_set.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/req/req_uninstall.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/candidates.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/factory.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/provider.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/reporter.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/requirements.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/resolution/resolvelib/resolver.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/self_outdated_check.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/_jaraco_text.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/_log.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/appdirs.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/compatibility_tags.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/datetime.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/deprecation.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/direct_url_helpers.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/egg_link.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/entrypoints.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/filesystem.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/filetypes.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/glibc.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/hashes.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/logging.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/misc.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/packaging.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/retry.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/setuptools_build.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/subprocess.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/temp_dir.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/unpacking.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/urls.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/virtualenv.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/utils/wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/vcs/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/vcs/bazaar.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/vcs/git.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/vcs/mercurial.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/vcs/subversion.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/vcs/versioncontrol.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_internal/wheel_builder.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/_cmd.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/adapter.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/cache.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/caches/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/controller.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/filewrapper.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/heuristics.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/serialize.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/cachecontrol/wrapper.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/certifi/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/certifi/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/certifi/core.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/certifi/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/dependency_groups/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/dependency_groups/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/dependency_groups/_implementation.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/dependency_groups/_lint_dependency_groups.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/dependency_groups/_pip_wrapper.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/dependency_groups/_toml_compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/dependency_groups/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/t32.exe delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/t64-arm.exe delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/t64.exe delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/util.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/w32.exe delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/w64-arm.exe delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distlib/w64.exe delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distro/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distro/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distro/distro.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/distro/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/codec.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/core.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/idnadata.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/intranges.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/package_data.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/idna/uts46data.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/msgpack/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/msgpack/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/msgpack/ext.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/msgpack/fallback.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/_elffile.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/_manylinux.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/_musllinux.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/_parser.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/_structures.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/_tokenizer.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/licenses/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/licenses/_spdx.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/markers.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/metadata.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/requirements.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/specifiers.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/tags.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/packaging/version.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pkg_resources/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/android.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/api.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/macos.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/unix.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/version.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/platformdirs/windows.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/console.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/filter.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/filters/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/formatter.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/formatters/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/formatters/_mapping.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/lexer.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/lexers/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/lexers/_mapping.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/lexers/python.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/modeline.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/plugin.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/regexopt.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/scanner.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/sphinxext.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/style.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/styles/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/styles/_mapping.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/token.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/unistring.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pygments/util.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/_impl.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/pyproject_hooks/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/__version__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/_internal_utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/api.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/auth.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/certs.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/help.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/models.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/packages.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/structures.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/requests/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/providers.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/reporters.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/resolvers/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/resolvers/abstract.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/resolvers/criterion.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/resolvers/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/resolvers/resolution.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/resolvelib/structs.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_cell_widths.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_emoji_codes.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_emoji_replace.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_export_format.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_extension.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_fileno.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_inspect.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_log_render.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_loop.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_null_file.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_palettes.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_pick.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_ratio.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_spinners.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_stack.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_timer.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_win32_console.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_windows.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_windows_renderer.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/_wrap.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/abc.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/align.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/ansi.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/bar.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/box.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/cells.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/color.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/color_triplet.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/columns.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/console.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/constrain.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/containers.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/control.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/default_styles.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/diagnose.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/emoji.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/errors.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/file_proxy.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/filesize.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/highlighter.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/json.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/jupyter.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/layout.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/live.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/live_render.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/logging.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/markup.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/measure.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/padding.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/pager.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/palette.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/panel.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/pretty.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/progress.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/progress_bar.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/prompt.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/protocol.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/region.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/repr.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/rule.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/scope.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/screen.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/segment.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/spinner.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/status.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/style.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/styled.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/syntax.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/table.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/terminal_theme.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/text.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/theme.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/themes.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/traceback.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/rich/tree.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli/_parser.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli/_re.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli/_types.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli_w/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli_w/_writer.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/tomli_w/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/truststore/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/truststore/_api.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/truststore/_macos.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/truststore/_openssl.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/truststore/_ssl_constants.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/truststore/_windows.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/truststore/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/_collections.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/_version.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/connection.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/connectionpool.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/appengine.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/securetransport.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/contrib/socks.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/fields.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/filepost.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/packages/six.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/poolmanager.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/request.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/response.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/connection.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/proxy.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/queue.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/request.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/response.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/retry.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/ssl_.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/ssltransport.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/timeout.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/url.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/urllib3/util/wait.py delete mode 100644 serverenv/lib/python3.9/site-packages/pip/_vendor/vendor.txt delete mode 100644 serverenv/lib/python3.9/site-packages/pip/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/appdirs.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__about__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_structures.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/_typing.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/markers.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/requirements.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/specifiers.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/tags.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/version.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/_vendor/pyparsing.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/extern/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/pkg_resources/tests/data/my-test-package-source/setup.py delete mode 100644 serverenv/lib/python3.9/site-packages/priority-2.0.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/priority-2.0.0.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/priority-2.0.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/priority-2.0.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/priority-2.0.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/priority-2.0.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/priority/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/priority/priority.py delete mode 100644 serverenv/lib/python3.9/site-packages/priority/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/quart-0.20.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/quart-0.20.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/quart-0.20.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/quart-0.20.0.dist-info/REQUESTED delete mode 100644 serverenv/lib/python3.9/site-packages/quart-0.20.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/quart-0.20.0.dist-info/entry_points.txt delete mode 100644 serverenv/lib/python3.9/site-packages/quart/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/__main__.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/app.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/asgi.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/blueprints.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/cli.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/config.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/ctx.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/datastructures.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/debug.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/formparser.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/globals.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/helpers.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/json/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/json/provider.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/json/tag.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/logging.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/quart/routing.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/sessions.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/signals.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/templating.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/testing/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/testing/app.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/testing/client.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/testing/connections.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/testing/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/typing.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/views.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/wrappers/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/wrappers/base.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/wrappers/request.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/wrappers/response.py delete mode 100644 serverenv/lib/python3.9/site-packages/quart/wrappers/websocket.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/REQUESTED delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/entry_points.txt delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools-58.0.4.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_deprecation_warning.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/_msvccompiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/archive_util.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/bcppcompiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/ccompiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/cmd.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/bdist.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/bdist_dumb.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/bdist_msi.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/bdist_rpm.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/bdist_wininst.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/build.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/build_clib.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/build_ext.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/build_py.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/build_scripts.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/check.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/clean.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/config.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/install.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/install_data.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/install_egg_info.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/install_headers.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/install_lib.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/install_scripts.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/py37compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/register.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/sdist.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/command/upload.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/config.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/core.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/cygwinccompiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/debug.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/dep_util.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/dir_util.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/dist.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/errors.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/extension.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/fancy_getopt.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/file_util.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/filelist.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/log.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/msvc9compiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/msvccompiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/py35compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/py38compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/spawn.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/sysconfig.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/text_file.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/unixccompiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/util.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/version.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_distutils/versionpredicate.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_imp.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/more.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/more_itertools/recipes.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/ordered_set.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__about__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_structures.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/_typing.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/markers.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/requirements.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/specifiers.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/tags.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/packaging/version.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/_vendor/pyparsing.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/archive_util.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/build_meta.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/cli-32.exe delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/cli-64.exe delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/cli.exe delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/alias.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/bdist_egg.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/bdist_rpm.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/build_clib.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/build_ext.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/build_py.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/develop.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/dist_info.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/easy_install.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/egg_info.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/install.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/install_egg_info.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/install_lib.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/install_scripts.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/launcher manifest.xml delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/py36compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/register.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/rotate.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/saveopts.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/sdist.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/setopt.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/test.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/upload.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/command/upload_docs.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/config.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/dep_util.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/depends.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/dist.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/errors.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/extension.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/extern/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/glob.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/gui-32.exe delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/gui-64.exe delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/gui.exe delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/installer.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/launch.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/monkey.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/msvc.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/namespaces.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/package_index.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/py34compat.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/sandbox.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/script (dev).tmpl delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/script.tmpl delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/unicode_utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/version.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/wheel.py delete mode 100644 serverenv/lib/python3.9/site-packages/setuptools/windows_support.py delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup-0.2.2.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup-0.2.2.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup-0.2.2.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup-0.2.2.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup-0.2.2.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup/install.py delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup/runners.py delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup/taskgroups.py delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup/tasks.py delete mode 100644 serverenv/lib/python3.9/site-packages/taskgroup/timeouts.py delete mode 100644 serverenv/lib/python3.9/site-packages/tomli-2.2.1.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/tomli-2.2.1.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/tomli-2.2.1.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/tomli-2.2.1.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/tomli-2.2.1.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/tomli/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/tomli/_parser.py delete mode 100644 serverenv/lib/python3.9/site-packages/tomli/_re.py delete mode 100644 serverenv/lib/python3.9/site-packages/tomli/_types.py delete mode 100644 serverenv/lib/python3.9/site-packages/tomli/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/typing_extensions-4.14.1.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/typing_extensions-4.14.1.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/typing_extensions-4.14.1.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/typing_extensions-4.14.1.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/typing_extensions-4.14.1.dist-info/licenses/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/typing_extensions.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug-3.1.3.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug-3.1.3.dist-info/LICENSE.txt delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug-3.1.3.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug-3.1.3.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug-3.1.3.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/_internal.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/_reloader.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/accept.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/auth.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/cache_control.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/csp.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/etag.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/file_storage.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/headers.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/mixins.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/range.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/datastructures/structures.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/console.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/repr.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/shared/ICON_LICENSE.md delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/shared/console.png delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/shared/debugger.js delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/shared/less.png delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/shared/more.png delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/shared/style.css delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/debug/tbtools.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/formparser.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/http.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/local.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/middleware/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/middleware/dispatcher.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/middleware/http_proxy.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/middleware/lint.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/middleware/profiler.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/middleware/shared_data.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/routing/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/routing/converters.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/routing/exceptions.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/routing/map.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/routing/matcher.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/routing/rules.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/sansio/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/sansio/http.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/sansio/multipart.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/sansio/request.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/sansio/response.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/sansio/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/security.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/serving.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/test.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/testapp.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/urls.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/user_agent.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/utils.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/wrappers/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/wrappers/request.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/wrappers/response.py delete mode 100644 serverenv/lib/python3.9/site-packages/werkzeug/wsgi.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto-1.2.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto-1.2.0.dist-info/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto-1.2.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto-1.2.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto-1.2.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto-1.2.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/connection.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/events.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/extensions.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/frame_protocol.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/handshake.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/py.typed delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/typing.py delete mode 100644 serverenv/lib/python3.9/site-packages/wsproto/utilities.py delete mode 100644 serverenv/lib/python3.9/site-packages/zipp-3.23.0.dist-info/INSTALLER delete mode 100644 serverenv/lib/python3.9/site-packages/zipp-3.23.0.dist-info/METADATA delete mode 100644 serverenv/lib/python3.9/site-packages/zipp-3.23.0.dist-info/RECORD delete mode 100644 serverenv/lib/python3.9/site-packages/zipp-3.23.0.dist-info/WHEEL delete mode 100644 serverenv/lib/python3.9/site-packages/zipp-3.23.0.dist-info/licenses/LICENSE delete mode 100644 serverenv/lib/python3.9/site-packages/zipp-3.23.0.dist-info/top_level.txt delete mode 100644 serverenv/lib/python3.9/site-packages/zipp/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/zipp/_functools.py delete mode 100644 serverenv/lib/python3.9/site-packages/zipp/compat/__init__.py delete mode 100644 serverenv/lib/python3.9/site-packages/zipp/compat/overlay.py delete mode 100644 serverenv/lib/python3.9/site-packages/zipp/compat/py310.py delete mode 100644 serverenv/lib/python3.9/site-packages/zipp/compat/py313.py delete mode 100644 serverenv/lib/python3.9/site-packages/zipp/glob.py delete mode 100644 serverenv/pyvenv.cfg diff --git a/serverenv/bin/Activate.ps1 b/serverenv/bin/Activate.ps1 deleted file mode 100644 index 2fb3852..0000000 --- a/serverenv/bin/Activate.ps1 +++ /dev/null @@ -1,241 +0,0 @@ -<# -.Synopsis -Activate a Python virtual environment for the current PowerShell session. - -.Description -Pushes the python executable for a virtual environment to the front of the -$Env:PATH environment variable and sets the prompt to signify that you are -in a Python virtual environment. Makes use of the command line switches as -well as the `pyvenv.cfg` file values present in the virtual environment. - -.Parameter VenvDir -Path to the directory that contains the virtual environment to activate. The -default value for this is the parent of the directory that the Activate.ps1 -script is located within. - -.Parameter Prompt -The prompt prefix to display when this virtual environment is activated. By -default, this prompt is the name of the virtual environment folder (VenvDir) -surrounded by parentheses and followed by a single space (ie. '(.venv) '). - -.Example -Activate.ps1 -Activates the Python virtual environment that contains the Activate.ps1 script. - -.Example -Activate.ps1 -Verbose -Activates the Python virtual environment that contains the Activate.ps1 script, -and shows extra information about the activation as it executes. - -.Example -Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv -Activates the Python virtual environment located in the specified location. - -.Example -Activate.ps1 -Prompt "MyPython" -Activates the Python virtual environment that contains the Activate.ps1 script, -and prefixes the current prompt with the specified string (surrounded in -parentheses) while the virtual environment is active. - -.Notes -On Windows, it may be required to enable this Activate.ps1 script by setting the -execution policy for the user. You can do this by issuing the following PowerShell -command: - -PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser - -For more information on Execution Policies: -https://go.microsoft.com/fwlink/?LinkID=135170 - -#> -Param( - [Parameter(Mandatory = $false)] - [String] - $VenvDir, - [Parameter(Mandatory = $false)] - [String] - $Prompt -) - -<# Function declarations --------------------------------------------------- #> - -<# -.Synopsis -Remove all shell session elements added by the Activate script, including the -addition of the virtual environment's Python executable from the beginning of -the PATH variable. - -.Parameter NonDestructive -If present, do not remove this function from the global namespace for the -session. - -#> -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - - # The prior prompt: - if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { - Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt - Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT - } - - # The prior PYTHONHOME: - if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { - Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME - Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME - } - - # The prior PATH: - if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { - Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH - Remove-Item -Path Env:_OLD_VIRTUAL_PATH - } - - # Just remove the VIRTUAL_ENV altogether: - if (Test-Path -Path Env:VIRTUAL_ENV) { - Remove-Item -Path env:VIRTUAL_ENV - } - - # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: - if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { - Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force - } - - # Leave deactivate function in the global namespace if requested: - if (-not $NonDestructive) { - Remove-Item -Path function:deactivate - } -} - -<# -.Description -Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the -given folder, and returns them in a map. - -For each line in the pyvenv.cfg file, if that line can be parsed into exactly -two strings separated by `=` (with any amount of whitespace surrounding the =) -then it is considered a `key = value` line. The left hand string is the key, -the right hand is the value. - -If the value starts with a `'` or a `"` then the first and last character is -stripped from the value before being captured. - -.Parameter ConfigDir -Path to the directory that contains the `pyvenv.cfg` file. -#> -function Get-PyVenvConfig( - [String] - $ConfigDir -) { - Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" - - # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). - $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue - - # An empty map will be returned if no config file is found. - $pyvenvConfig = @{ } - - if ($pyvenvConfigPath) { - - Write-Verbose "File exists, parse `key = value` lines" - $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath - - $pyvenvConfigContent | ForEach-Object { - $keyval = $PSItem -split "\s*=\s*", 2 - if ($keyval[0] -and $keyval[1]) { - $val = $keyval[1] - - # Remove extraneous quotations around a string value. - if ("'""".Contains($val.Substring(0, 1))) { - $val = $val.Substring(1, $val.Length - 2) - } - - $pyvenvConfig[$keyval[0]] = $val - Write-Verbose "Adding Key: '$($keyval[0])'='$val'" - } - } - } - return $pyvenvConfig -} - - -<# Begin Activate script --------------------------------------------------- #> - -# Determine the containing directory of this script -$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition -$VenvExecDir = Get-Item -Path $VenvExecPath - -Write-Verbose "Activation script is located in path: '$VenvExecPath'" -Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" -Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" - -# Set values required in priority: CmdLine, ConfigFile, Default -# First, get the location of the virtual environment, it might not be -# VenvExecDir if specified on the command line. -if ($VenvDir) { - Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" -} -else { - Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." - $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") - Write-Verbose "VenvDir=$VenvDir" -} - -# Next, read the `pyvenv.cfg` file to determine any required value such -# as `prompt`. -$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir - -# Next, set the prompt from the command line, or the config file, or -# just use the name of the virtual environment folder. -if ($Prompt) { - Write-Verbose "Prompt specified as argument, using '$Prompt'" -} -else { - Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" - if ($pyvenvCfg -and $pyvenvCfg['prompt']) { - Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" - $Prompt = $pyvenvCfg['prompt']; - } - else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" - Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" - $Prompt = Split-Path -Path $venvDir -Leaf - } -} - -Write-Verbose "Prompt = '$Prompt'" -Write-Verbose "VenvDir='$VenvDir'" - -# Deactivate any currently active virtual environment, but leave the -# deactivate function in place. -deactivate -nondestructive - -# Now set the environment variable VIRTUAL_ENV, used by many tools to determine -# that there is an activated venv. -$env:VIRTUAL_ENV = $VenvDir - -if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { - - Write-Verbose "Setting prompt to '$Prompt'" - - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT { "" } - Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT - New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt - - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " - _OLD_VIRTUAL_PROMPT - } -} - -# Clear PYTHONHOME -if (Test-Path -Path Env:PYTHONHOME) { - Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME - Remove-Item -Path Env:PYTHONHOME -} - -# Add the venv to the PATH -Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH -$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/serverenv/bin/activate b/serverenv/bin/activate deleted file mode 100644 index 5c7ae92..0000000 --- a/serverenv/bin/activate +++ /dev/null @@ -1,66 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then - PATH="${_OLD_VIRTUAL_PATH:-}" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then - PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then - hash -r 2> /dev/null - fi - - if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then - PS1="${_OLD_VIRTUAL_PS1:-}" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - if [ ! "${1:-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -VIRTUAL_ENV="/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv" -export VIRTUAL_ENV - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/bin:$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME:-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1:-}" - PS1="(serverenv) ${PS1:-}" - export PS1 -fi - -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then - hash -r 2> /dev/null -fi diff --git a/serverenv/bin/activate.csh b/serverenv/bin/activate.csh deleted file mode 100644 index 70eadf9..0000000 --- a/serverenv/bin/activate.csh +++ /dev/null @@ -1,25 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv" - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/bin:$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - set prompt = "(serverenv) $prompt" -endif - -alias pydoc python -m pydoc - -rehash diff --git a/serverenv/bin/activate.fish b/serverenv/bin/activate.fish deleted file mode 100644 index 4e4d64d..0000000 --- a/serverenv/bin/activate.fish +++ /dev/null @@ -1,64 +0,0 @@ -# This file must be used with "source /bin/activate.fish" *from fish* -# (https://fishshell.com/); you cannot run it directly. - -function deactivate -d "Exit virtual environment and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - functions -e fish_prompt - set -e _OLD_FISH_PROMPT_OVERRIDE - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - end - - set -e VIRTUAL_ENV - if test "$argv[1]" != "nondestructive" - # Self-destruct! - functions -e deactivate - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV "/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv" - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/bin" $PATH - -# Unset PYTHONHOME if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # Save the current fish_prompt function as the function _old_fish_prompt. - functions -c fish_prompt _old_fish_prompt - - # With the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command. - set -l old_status $status - - # Output the venv prompt; color taken from the blue of the Python logo. - printf "%s%s%s" (set_color 4B8BBE) "(serverenv) " (set_color normal) - - # Restore the return status of the previous command. - echo "exit $old_status" | . - # Output the original/"old" prompt. - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" -end diff --git a/serverenv/bin/flask b/serverenv/bin/flask deleted file mode 100755 index 7f86025..0000000 --- a/serverenv/bin/flask +++ /dev/null @@ -1,7 +0,0 @@ -#!/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/bin/python3 -import sys -from flask.cli import main -if __name__ == '__main__': - if sys.argv[0].endswith('.exe'): - sys.argv[0] = sys.argv[0][:-4] - sys.exit(main()) diff --git a/serverenv/bin/hypercorn b/serverenv/bin/hypercorn deleted file mode 100755 index a8c6300..0000000 --- a/serverenv/bin/hypercorn +++ /dev/null @@ -1,7 +0,0 @@ -#!/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/bin/python3 -import sys -from hypercorn.__main__ import main -if __name__ == '__main__': - if sys.argv[0].endswith('.exe'): - sys.argv[0] = sys.argv[0][:-4] - sys.exit(main()) diff --git a/serverenv/bin/pip b/serverenv/bin/pip deleted file mode 100755 index 214d27c..0000000 --- a/serverenv/bin/pip +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/serverenv/bin/pip3 b/serverenv/bin/pip3 deleted file mode 100755 index 214d27c..0000000 --- a/serverenv/bin/pip3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/serverenv/bin/pip3.9 b/serverenv/bin/pip3.9 deleted file mode 100755 index 214d27c..0000000 --- a/serverenv/bin/pip3.9 +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/serverenv/bin/python b/serverenv/bin/python deleted file mode 120000 index b8a0adb..0000000 --- a/serverenv/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3 \ No newline at end of file diff --git a/serverenv/bin/python3 b/serverenv/bin/python3 deleted file mode 120000 index f25545f..0000000 --- a/serverenv/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -/Library/Developer/CommandLineTools/usr/bin/python3 \ No newline at end of file diff --git a/serverenv/bin/python3.9 b/serverenv/bin/python3.9 deleted file mode 120000 index b8a0adb..0000000 --- a/serverenv/bin/python3.9 +++ /dev/null @@ -1 +0,0 @@ -python3 \ No newline at end of file diff --git a/serverenv/bin/quart b/serverenv/bin/quart deleted file mode 100755 index 807a1c1..0000000 --- a/serverenv/bin/quart +++ /dev/null @@ -1,7 +0,0 @@ -#!/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/bin/python3 -import sys -from quart.cli import main -if __name__ == '__main__': - if sys.argv[0].endswith('.exe'): - sys.argv[0] = sys.argv[0][:-4] - sys.exit(main()) diff --git a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt b/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt deleted file mode 100644 index 9d227a0..0000000 --- a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2010 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/METADATA deleted file mode 100644 index 82261f2..0000000 --- a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/METADATA +++ /dev/null @@ -1,92 +0,0 @@ -Metadata-Version: 2.1 -Name: MarkupSafe -Version: 3.0.2 -Summary: Safely add untrusted strings to HTML/XML markup. -Maintainer-email: Pallets -License: Copyright 2010 Pallets - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Project-URL: Donate, https://palletsprojects.com/donate -Project-URL: Documentation, https://markupsafe.palletsprojects.com/ -Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ -Project-URL: Source, https://github.com/pallets/markupsafe/ -Project-URL: Chat, https://discord.gg/pallets -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Text Processing :: Markup :: HTML -Classifier: Typing :: Typed -Requires-Python: >=3.9 -Description-Content-Type: text/markdown -License-File: LICENSE.txt - -# MarkupSafe - -MarkupSafe implements a text object that escapes characters so it is -safe to use in HTML and XML. Characters that have special meanings are -replaced so that they display as the actual characters. This mitigates -injection attacks, meaning untrusted user input can safely be displayed -on a page. - - -## Examples - -```pycon ->>> from markupsafe import Markup, escape - ->>> # escape replaces special characters and wraps in Markup ->>> escape("") -Markup('<script>alert(document.cookie);</script>') - ->>> # wrap in Markup to mark text "safe" and prevent escaping ->>> Markup("Hello") -Markup('hello') - ->>> escape(Markup("Hello")) -Markup('hello') - ->>> # Markup is a str subclass ->>> # methods and operators escape their arguments ->>> template = Markup("Hello {name}") ->>> template.format(name='"World"') -Markup('Hello "World"') -``` - -## Donate - -The Pallets organization develops and supports MarkupSafe and other -popular packages. In order to grow the community of contributors and -users, and allow the maintainers to devote more time to the projects, -[please donate today][]. - -[please donate today]: https://palletsprojects.com/donate diff --git a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/RECORD deleted file mode 100644 index ed65342..0000000 --- a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/RECORD +++ /dev/null @@ -1,14 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/markupsafe/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/markupsafe/_native.cpython-39.pyc,, -MarkupSafe-3.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -MarkupSafe-3.0.2.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 -MarkupSafe-3.0.2.dist-info/METADATA,sha256=aAwbZhSmXdfFuMM-rEHpeiHRkBOGESyVLJIuwzHP-nw,3975 -MarkupSafe-3.0.2.dist-info/RECORD,, -MarkupSafe-3.0.2.dist-info/WHEEL,sha256=qPSLW7RKkSazFLr9GqnCq82B2cy1OopxhNJnY83fx9k,107 -MarkupSafe-3.0.2.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 -markupsafe/__init__.py,sha256=sr-U6_27DfaSrj5jnHYxWN-pvhM27sjlDplMDPZKm7k,13214 -markupsafe/_native.py,sha256=hSLs8Jmz5aqayuengJJ3kdT5PwNpBWpKrmQSdipndC8,210 -markupsafe/_speedups.c,sha256=O7XulmTo-epI6n2FtMVOrJXl8EAaIwD2iNYmBI5SEoQ,4149 -markupsafe/_speedups.cpython-39-darwin.so,sha256=3kO9hwZrfNqylESEkM3jZAKLiK1u2xcJVWykvvGgimk,50688 -markupsafe/_speedups.pyi,sha256=ENd1bYe7gbBUf2ywyYWOGUpnXOHNJ-cgTNqetlW8h5k,41 -markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL deleted file mode 100644 index 06a9871..0000000 --- a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (75.2.0) -Root-Is-Purelib: false -Tag: cp39-cp39-macosx_11_0_arm64 - diff --git a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt b/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt deleted file mode 100644 index 75bf729..0000000 --- a/serverenv/lib/python3.9/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -markupsafe diff --git a/serverenv/lib/python3.9/site-packages/_distutils_hack/__init__.py b/serverenv/lib/python3.9/site-packages/_distutils_hack/__init__.py deleted file mode 100644 index 5f40996..0000000 --- a/serverenv/lib/python3.9/site-packages/_distutils_hack/__init__.py +++ /dev/null @@ -1,128 +0,0 @@ -import sys -import os -import re -import importlib -import warnings - - -is_pypy = '__pypy__' in sys.builtin_module_names - - -warnings.filterwarnings('ignore', - r'.+ distutils\b.+ deprecated', - DeprecationWarning) - - -def warn_distutils_present(): - if 'distutils' not in sys.modules: - return - if is_pypy and sys.version_info < (3, 7): - # PyPy for 3.6 unconditionally imports distutils, so bypass the warning - # https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250 - return - warnings.warn( - "Distutils was imported before Setuptools, but importing Setuptools " - "also replaces the `distutils` module in `sys.modules`. This may lead " - "to undesirable behaviors or errors. To avoid these issues, avoid " - "using distutils directly, ensure that setuptools is installed in the " - "traditional way (e.g. not an editable install), and/or make sure " - "that setuptools is always imported before distutils.") - - -def clear_distutils(): - if 'distutils' not in sys.modules: - return - warnings.warn("Setuptools is replacing distutils.") - mods = [name for name in sys.modules if re.match(r'distutils\b', name)] - for name in mods: - del sys.modules[name] - - -def enabled(): - """ - Allow selection of distutils by environment variable. - """ - which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'stdlib') - return which == 'local' - - -def ensure_local_distutils(): - clear_distutils() - distutils = importlib.import_module('setuptools._distutils') - distutils.__name__ = 'distutils' - sys.modules['distutils'] = distutils - - # sanity check that submodules load as expected - core = importlib.import_module('distutils.core') - assert '_distutils' in core.__file__, core.__file__ - - -def do_override(): - """ - Ensure that the local copy of distutils is preferred over stdlib. - - See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401 - for more motivation. - """ - if enabled(): - warn_distutils_present() - ensure_local_distutils() - - -class DistutilsMetaFinder: - def find_spec(self, fullname, path, target=None): - if path is not None: - return - - method_name = 'spec_for_{fullname}'.format(**locals()) - method = getattr(self, method_name, lambda: None) - return method() - - def spec_for_distutils(self): - import importlib.abc - import importlib.util - - class DistutilsLoader(importlib.abc.Loader): - - def create_module(self, spec): - return importlib.import_module('setuptools._distutils') - - def exec_module(self, module): - pass - - return importlib.util.spec_from_loader('distutils', DistutilsLoader()) - - def spec_for_pip(self): - """ - Ensure stdlib distutils when running under pip. - See pypa/pip#8761 for rationale. - """ - if self.pip_imported_during_build(): - return - clear_distutils() - self.spec_for_distutils = lambda: None - - @staticmethod - def pip_imported_during_build(): - """ - Detect if pip is being imported in a build script. Ref #2355. - """ - import traceback - return any( - frame.f_globals['__file__'].endswith('setup.py') - for frame, line in traceback.walk_stack(None) - ) - - -DISTUTILS_FINDER = DistutilsMetaFinder() - - -def add_shim(): - sys.meta_path.insert(0, DISTUTILS_FINDER) - - -def remove_shim(): - try: - sys.meta_path.remove(DISTUTILS_FINDER) - except ValueError: - pass diff --git a/serverenv/lib/python3.9/site-packages/_distutils_hack/override.py b/serverenv/lib/python3.9/site-packages/_distutils_hack/override.py deleted file mode 100644 index 2cc433a..0000000 --- a/serverenv/lib/python3.9/site-packages/_distutils_hack/override.py +++ /dev/null @@ -1 +0,0 @@ -__import__('_distutils_hack').do_override() diff --git a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/METADATA deleted file mode 100644 index 942d74c..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/METADATA +++ /dev/null @@ -1,318 +0,0 @@ -Metadata-Version: 2.3 -Name: aiofiles -Version: 24.1.0 -Summary: File support for asyncio. -Project-URL: Changelog, https://github.com/Tinche/aiofiles#history -Project-URL: Bug Tracker, https://github.com/Tinche/aiofiles/issues -Project-URL: repository, https://github.com/Tinche/aiofiles -Author-email: Tin Tvrtkovic -License: Apache-2.0 -License-File: LICENSE -License-File: NOTICE -Classifier: Development Status :: 5 - Production/Stable -Classifier: Framework :: AsyncIO -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.8 -Description-Content-Type: text/markdown - -# aiofiles: file support for asyncio - -[![PyPI](https://img.shields.io/pypi/v/aiofiles.svg)](https://pypi.python.org/pypi/aiofiles) -[![Build](https://github.com/Tinche/aiofiles/workflows/CI/badge.svg)](https://github.com/Tinche/aiofiles/actions) -[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/Tinche/882f02e3df32136c847ba90d2688f06e/raw/covbadge.json)](https://github.com/Tinche/aiofiles/actions/workflows/main.yml) -[![Supported Python versions](https://img.shields.io/pypi/pyversions/aiofiles.svg)](https://github.com/Tinche/aiofiles) -[![Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) - -**aiofiles** is an Apache2 licensed library, written in Python, for handling local -disk files in asyncio applications. - -Ordinary local file IO is blocking, and cannot easily and portably be made -asynchronous. This means doing file IO may interfere with asyncio applications, -which shouldn't block the executing thread. aiofiles helps with this by -introducing asynchronous versions of files that support delegating operations to -a separate thread pool. - -```python -async with aiofiles.open('filename', mode='r') as f: - contents = await f.read() -print(contents) -'My file contents' -``` - -Asynchronous iteration is also supported. - -```python -async with aiofiles.open('filename') as f: - async for line in f: - ... -``` - -Asynchronous interface to tempfile module. - -```python -async with aiofiles.tempfile.TemporaryFile('wb') as f: - await f.write(b'Hello, World!') -``` - -## Features - -- a file API very similar to Python's standard, blocking API -- support for buffered and unbuffered binary files, and buffered text files -- support for `async`/`await` ([PEP 492](https://peps.python.org/pep-0492/)) constructs -- async interface to tempfile module - -## Installation - -To install aiofiles, simply: - -```bash -$ pip install aiofiles -``` - -## Usage - -Files are opened using the `aiofiles.open()` coroutine, which in addition to -mirroring the builtin `open` accepts optional `loop` and `executor` -arguments. If `loop` is absent, the default loop will be used, as per the -set asyncio policy. If `executor` is not specified, the default event loop -executor will be used. - -In case of success, an asynchronous file object is returned with an -API identical to an ordinary file, except the following methods are coroutines -and delegate to an executor: - -- `close` -- `flush` -- `isatty` -- `read` -- `readall` -- `read1` -- `readinto` -- `readline` -- `readlines` -- `seek` -- `seekable` -- `tell` -- `truncate` -- `writable` -- `write` -- `writelines` - -In case of failure, one of the usual exceptions will be raised. - -`aiofiles.stdin`, `aiofiles.stdout`, `aiofiles.stderr`, -`aiofiles.stdin_bytes`, `aiofiles.stdout_bytes`, and -`aiofiles.stderr_bytes` provide async access to `sys.stdin`, -`sys.stdout`, `sys.stderr`, and their corresponding `.buffer` properties. - -The `aiofiles.os` module contains executor-enabled coroutine versions of -several useful `os` functions that deal with files: - -- `stat` -- `statvfs` -- `sendfile` -- `rename` -- `renames` -- `replace` -- `remove` -- `unlink` -- `mkdir` -- `makedirs` -- `rmdir` -- `removedirs` -- `link` -- `symlink` -- `readlink` -- `listdir` -- `scandir` -- `access` -- `getcwd` -- `path.abspath` -- `path.exists` -- `path.isfile` -- `path.isdir` -- `path.islink` -- `path.ismount` -- `path.getsize` -- `path.getatime` -- `path.getctime` -- `path.samefile` -- `path.sameopenfile` - -### Tempfile - -**aiofiles.tempfile** implements the following interfaces: - -- TemporaryFile -- NamedTemporaryFile -- SpooledTemporaryFile -- TemporaryDirectory - -Results return wrapped with a context manager allowing use with async with and async for. - -```python -async with aiofiles.tempfile.NamedTemporaryFile('wb+') as f: - await f.write(b'Line1\n Line2') - await f.seek(0) - async for line in f: - print(line) - -async with aiofiles.tempfile.TemporaryDirectory() as d: - filename = os.path.join(d, "file.ext") -``` - -### Writing tests for aiofiles - -Real file IO can be mocked by patching `aiofiles.threadpool.sync_open` -as desired. The return type also needs to be registered with the -`aiofiles.threadpool.wrap` dispatcher: - -```python -aiofiles.threadpool.wrap.register(mock.MagicMock)( - lambda *args, **kwargs: aiofiles.threadpool.AsyncBufferedIOBase(*args, **kwargs) -) - -async def test_stuff(): - write_data = 'data' - read_file_chunks = [ - b'file chunks 1', - b'file chunks 2', - b'file chunks 3', - b'', - ] - file_chunks_iter = iter(read_file_chunks) - - mock_file_stream = mock.MagicMock( - read=lambda *args, **kwargs: next(file_chunks_iter) - ) - - with mock.patch('aiofiles.threadpool.sync_open', return_value=mock_file_stream) as mock_open: - async with aiofiles.open('filename', 'w') as f: - await f.write(write_data) - assert f.read() == b'file chunks 1' - - mock_file_stream.write.assert_called_once_with(write_data) -``` - -### History - -#### 24.1.0 (2024-06-24) - -- Import `os.link` conditionally to fix importing on android. - [#175](https://github.com/Tinche/aiofiles/issues/175) -- Remove spurious items from `aiofiles.os.__all__` when running on Windows. -- Switch to more modern async idioms: Remove types.coroutine and make AiofilesContextManager an awaitable instead a coroutine. -- Add `aiofiles.os.path.abspath` and `aiofiles.os.getcwd`. - [#174](https://github.com/Tinche/aiofiles/issues/181) -- _aiofiles_ is now tested on Python 3.13 too. - [#184](https://github.com/Tinche/aiofiles/pull/184) -- Dropped Python 3.7 support. If you require it, use version 23.2.1. - -#### 23.2.1 (2023-08-09) - -- Import `os.statvfs` conditionally to fix importing on non-UNIX systems. - [#171](https://github.com/Tinche/aiofiles/issues/171) [#172](https://github.com/Tinche/aiofiles/pull/172) -- aiofiles is now also tested on Windows. - -#### 23.2.0 (2023-08-09) - -- aiofiles is now tested on Python 3.12 too. - [#166](https://github.com/Tinche/aiofiles/issues/166) [#168](https://github.com/Tinche/aiofiles/pull/168) -- On Python 3.12, `aiofiles.tempfile.NamedTemporaryFile` now accepts a `delete_on_close` argument, just like the stdlib version. -- On Python 3.12, `aiofiles.tempfile.NamedTemporaryFile` no longer exposes a `delete` attribute, just like the stdlib version. -- Added `aiofiles.os.statvfs` and `aiofiles.os.path.ismount`. - [#162](https://github.com/Tinche/aiofiles/pull/162) -- Use [PDM](https://pdm.fming.dev/latest/) instead of Poetry. - [#169](https://github.com/Tinche/aiofiles/pull/169) - -#### 23.1.0 (2023-02-09) - -- Added `aiofiles.os.access`. - [#146](https://github.com/Tinche/aiofiles/pull/146) -- Removed `aiofiles.tempfile.temptypes.AsyncSpooledTemporaryFile.softspace`. - [#151](https://github.com/Tinche/aiofiles/pull/151) -- Added `aiofiles.stdin`, `aiofiles.stdin_bytes`, and other stdio streams. - [#154](https://github.com/Tinche/aiofiles/pull/154) -- Transition to `asyncio.get_running_loop` (vs `asyncio.get_event_loop`) internally. - -#### 22.1.0 (2022-09-04) - -- Added `aiofiles.os.path.islink`. - [#126](https://github.com/Tinche/aiofiles/pull/126) -- Added `aiofiles.os.readlink`. - [#125](https://github.com/Tinche/aiofiles/pull/125) -- Added `aiofiles.os.symlink`. - [#124](https://github.com/Tinche/aiofiles/pull/124) -- Added `aiofiles.os.unlink`. - [#123](https://github.com/Tinche/aiofiles/pull/123) -- Added `aiofiles.os.link`. - [#121](https://github.com/Tinche/aiofiles/pull/121) -- Added `aiofiles.os.renames`. - [#120](https://github.com/Tinche/aiofiles/pull/120) -- Added `aiofiles.os.{listdir, scandir}`. - [#143](https://github.com/Tinche/aiofiles/pull/143) -- Switched to CalVer. -- Dropped Python 3.6 support. If you require it, use version 0.8.0. -- aiofiles is now tested on Python 3.11. - -#### 0.8.0 (2021-11-27) - -- aiofiles is now tested on Python 3.10. -- Added `aiofiles.os.replace`. - [#107](https://github.com/Tinche/aiofiles/pull/107) -- Added `aiofiles.os.{makedirs, removedirs}`. -- Added `aiofiles.os.path.{exists, isfile, isdir, getsize, getatime, getctime, samefile, sameopenfile}`. - [#63](https://github.com/Tinche/aiofiles/pull/63) -- Added `suffix`, `prefix`, `dir` args to `aiofiles.tempfile.TemporaryDirectory`. - [#116](https://github.com/Tinche/aiofiles/pull/116) - -#### 0.7.0 (2021-05-17) - -- Added the `aiofiles.tempfile` module for async temporary files. - [#56](https://github.com/Tinche/aiofiles/pull/56) -- Switched to Poetry and GitHub actions. -- Dropped 3.5 support. - -#### 0.6.0 (2020-10-27) - -- `aiofiles` is now tested on ppc64le. -- Added `name` and `mode` properties to async file objects. - [#82](https://github.com/Tinche/aiofiles/pull/82) -- Fixed a DeprecationWarning internally. - [#75](https://github.com/Tinche/aiofiles/pull/75) -- Python 3.9 support and tests. - -#### 0.5.0 (2020-04-12) - -- Python 3.8 support. Code base modernization (using `async/await` instead of `asyncio.coroutine`/`yield from`). -- Added `aiofiles.os.remove`, `aiofiles.os.rename`, `aiofiles.os.mkdir`, `aiofiles.os.rmdir`. - [#62](https://github.com/Tinche/aiofiles/pull/62) - -#### 0.4.0 (2018-08-11) - -- Python 3.7 support. -- Removed Python 3.3/3.4 support. If you use these versions, stick to aiofiles 0.3.x. - -#### 0.3.2 (2017-09-23) - -- The LICENSE is now included in the sdist. - [#31](https://github.com/Tinche/aiofiles/pull/31) - -#### 0.3.1 (2017-03-10) - -- Introduced a changelog. -- `aiofiles.os.sendfile` will now work if the standard `os` module contains a `sendfile` function. - -### Contributing - -Contributions are very welcome. Tests can be run with `tox`, please ensure -the coverage at least stays the same before you submit a pull request. diff --git a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/RECORD deleted file mode 100644 index 5766a89..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/RECORD +++ /dev/null @@ -1,26 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/base.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/os.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/ospath.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/temptypes.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/binary.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/text.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/utils.cpython-39.pyc,, -aiofiles-24.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -aiofiles-24.1.0.dist-info/METADATA,sha256=CvUJx21XclgI1Lp5Bt_4AyJesRYg0xCSx4exJZVmaSA,10708 -aiofiles-24.1.0.dist-info/RECORD,, -aiofiles-24.1.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87 -aiofiles-24.1.0.dist-info/licenses/LICENSE,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325 -aiofiles-24.1.0.dist-info/licenses/NOTICE,sha256=EExY0dRQvWR0wJ2LZLwBgnM6YKw9jCU-M0zegpRSD_E,55 -aiofiles/__init__.py,sha256=1iAMJQyJtX3LGIS0AoFTJeO1aJ_RK2jpBSBhg0VoIrE,344 -aiofiles/base.py,sha256=zo0FgkCqZ5aosjvxqIvDf2t-RFg1Lc6X8P6rZ56p6fQ,1784 -aiofiles/os.py,sha256=0DrsG-eH4h7xRzglv9pIWsQuzqe7ZhVYw5FQS18fIys,1153 -aiofiles/ospath.py,sha256=WaYelz_k6ykAFRLStr4bqYIfCVQ-5GGzIqIizykbY2Q,794 -aiofiles/tempfile/__init__.py,sha256=hFSNTOjOUv371Ozdfy6FIxeln46Nm3xOVh4ZR3Q94V0,10244 -aiofiles/tempfile/temptypes.py,sha256=ddEvNjMLVlr7WUILCe6ypTqw77yREeIonTk16Uw_NVs,2093 -aiofiles/threadpool/__init__.py,sha256=kt0hwwx3bLiYtnA1SORhW8mJ6z4W9Xr7MbY80UIJJrI,3133 -aiofiles/threadpool/binary.py,sha256=hp-km9VCRu0MLz_wAEUfbCz7OL7xtn9iGAawabpnp5U,2315 -aiofiles/threadpool/text.py,sha256=fNmpw2PEkj0BZSldipJXAgZqVGLxALcfOMiuDQ54Eas,1223 -aiofiles/threadpool/utils.py,sha256=B59dSZwO_WZs2dFFycKeA91iD2Xq2nNw1EFF8YMBI5k,1868 diff --git a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/WHEEL deleted file mode 100644 index cdd68a4..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.25.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/LICENSE b/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/LICENSE deleted file mode 100644 index e06d208..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/NOTICE b/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/NOTICE deleted file mode 100644 index d134f28..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles-24.1.0.dist-info/licenses/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -Asyncio support for files -Copyright 2016 Tin Tvrtkovic diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/__init__.py b/serverenv/lib/python3.9/site-packages/aiofiles/__init__.py deleted file mode 100644 index 9e75111..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Utilities for asyncio-friendly file handling.""" -from .threadpool import ( - open, - stdin, - stdout, - stderr, - stdin_bytes, - stdout_bytes, - stderr_bytes, -) -from . import tempfile - -__all__ = [ - "open", - "tempfile", - "stdin", - "stdout", - "stderr", - "stdin_bytes", - "stdout_bytes", - "stderr_bytes", -] diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/base.py b/serverenv/lib/python3.9/site-packages/aiofiles/base.py deleted file mode 100644 index 64f7d6b..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/base.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Various base classes.""" -from collections.abc import Awaitable -from contextlib import AbstractAsyncContextManager -from asyncio import get_running_loop - - -class AsyncBase: - def __init__(self, file, loop, executor): - self._file = file - self._executor = executor - self._ref_loop = loop - - @property - def _loop(self): - return self._ref_loop or get_running_loop() - - def __aiter__(self): - """We are our own iterator.""" - return self - - def __repr__(self): - return super().__repr__() + " wrapping " + repr(self._file) - - async def __anext__(self): - """Simulate normal file iteration.""" - line = await self.readline() - if line: - return line - else: - raise StopAsyncIteration - - -class AsyncIndirectBase(AsyncBase): - def __init__(self, name, loop, executor, indirect): - self._indirect = indirect - self._name = name - super().__init__(None, loop, executor) - - @property - def _file(self): - return self._indirect() - - @_file.setter - def _file(self, v): - pass # discard writes - - -class AiofilesContextManager(Awaitable, AbstractAsyncContextManager): - """An adjusted async context manager for aiofiles.""" - - __slots__ = ("_coro", "_obj") - - def __init__(self, coro): - self._coro = coro - self._obj = None - - def __await__(self): - if self._obj is None: - self._obj = yield from self._coro.__await__() - return self._obj - - async def __aenter__(self): - return await self - - async def __aexit__(self, exc_type, exc_val, exc_tb): - await get_running_loop().run_in_executor( - None, self._obj._file.__exit__, exc_type, exc_val, exc_tb - ) - self._obj = None diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/os.py b/serverenv/lib/python3.9/site-packages/aiofiles/os.py deleted file mode 100644 index 92243fa..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/os.py +++ /dev/null @@ -1,58 +0,0 @@ -"""Async executor versions of file functions from the os module.""" - -import os - -from . import ospath as path -from .ospath import wrap - -__all__ = [ - "path", - "stat", - "rename", - "renames", - "replace", - "remove", - "unlink", - "mkdir", - "makedirs", - "rmdir", - "removedirs", - "symlink", - "readlink", - "listdir", - "scandir", - "access", - "wrap", - "getcwd", -] -if hasattr(os, "link"): - __all__ += ["link"] -if hasattr(os, "sendfile"): - __all__ += ["sendfile"] -if hasattr(os, "statvfs"): - __all__ += ["statvfs"] - - -stat = wrap(os.stat) -rename = wrap(os.rename) -renames = wrap(os.renames) -replace = wrap(os.replace) -remove = wrap(os.remove) -unlink = wrap(os.unlink) -mkdir = wrap(os.mkdir) -makedirs = wrap(os.makedirs) -rmdir = wrap(os.rmdir) -removedirs = wrap(os.removedirs) -symlink = wrap(os.symlink) -readlink = wrap(os.readlink) -listdir = wrap(os.listdir) -scandir = wrap(os.scandir) -access = wrap(os.access) -getcwd = wrap(os.getcwd) - -if hasattr(os, "link"): - link = wrap(os.link) -if hasattr(os, "sendfile"): - sendfile = wrap(os.sendfile) -if hasattr(os, "statvfs"): - statvfs = wrap(os.statvfs) diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/ospath.py b/serverenv/lib/python3.9/site-packages/aiofiles/ospath.py deleted file mode 100644 index 387d68d..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/ospath.py +++ /dev/null @@ -1,30 +0,0 @@ -"""Async executor versions of file functions from the os.path module.""" - -import asyncio -from functools import partial, wraps -from os import path - - -def wrap(func): - @wraps(func) - async def run(*args, loop=None, executor=None, **kwargs): - if loop is None: - loop = asyncio.get_running_loop() - pfunc = partial(func, *args, **kwargs) - return await loop.run_in_executor(executor, pfunc) - - return run - - -exists = wrap(path.exists) -isfile = wrap(path.isfile) -isdir = wrap(path.isdir) -islink = wrap(path.islink) -ismount = wrap(path.ismount) -getsize = wrap(path.getsize) -getmtime = wrap(path.getmtime) -getatime = wrap(path.getatime) -getctime = wrap(path.getctime) -samefile = wrap(path.samefile) -sameopenfile = wrap(path.sameopenfile) -abspath = wrap(path.abspath) diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/__init__.py b/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/__init__.py deleted file mode 100644 index ac3f8bd..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/__init__.py +++ /dev/null @@ -1,357 +0,0 @@ -import asyncio -from functools import partial, singledispatch -from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOBase -from tempfile import NamedTemporaryFile as syncNamedTemporaryFile -from tempfile import SpooledTemporaryFile as syncSpooledTemporaryFile -from tempfile import TemporaryDirectory as syncTemporaryDirectory -from tempfile import TemporaryFile as syncTemporaryFile -from tempfile import _TemporaryFileWrapper as syncTemporaryFileWrapper - -from ..base import AiofilesContextManager -from ..threadpool.binary import AsyncBufferedIOBase, AsyncBufferedReader, AsyncFileIO -from ..threadpool.text import AsyncTextIOWrapper -from .temptypes import AsyncSpooledTemporaryFile, AsyncTemporaryDirectory -import sys - -__all__ = [ - "NamedTemporaryFile", - "TemporaryFile", - "SpooledTemporaryFile", - "TemporaryDirectory", -] - - -# ================================================================ -# Public methods for async open and return of temp file/directory -# objects with async interface -# ================================================================ -if sys.version_info >= (3, 12): - - def NamedTemporaryFile( - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - delete=True, - delete_on_close=True, - loop=None, - executor=None, - ): - """Async open a named temporary file""" - return AiofilesContextManager( - _temporary_file( - named=True, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - delete=delete, - delete_on_close=delete_on_close, - loop=loop, - executor=executor, - ) - ) - -else: - - def NamedTemporaryFile( - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - delete=True, - loop=None, - executor=None, - ): - """Async open a named temporary file""" - return AiofilesContextManager( - _temporary_file( - named=True, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - delete=delete, - loop=loop, - executor=executor, - ) - ) - - -def TemporaryFile( - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - loop=None, - executor=None, -): - """Async open an unnamed temporary file""" - return AiofilesContextManager( - _temporary_file( - named=False, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - loop=loop, - executor=executor, - ) - ) - - -def SpooledTemporaryFile( - max_size=0, - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - loop=None, - executor=None, -): - """Async open a spooled temporary file""" - return AiofilesContextManager( - _spooled_temporary_file( - max_size=max_size, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - loop=loop, - executor=executor, - ) - ) - - -def TemporaryDirectory(suffix=None, prefix=None, dir=None, loop=None, executor=None): - """Async open a temporary directory""" - return AiofilesContextManagerTempDir( - _temporary_directory( - suffix=suffix, prefix=prefix, dir=dir, loop=loop, executor=executor - ) - ) - - -# ========================================================= -# Internal coroutines to open new temp files/directories -# ========================================================= -if sys.version_info >= (3, 12): - - async def _temporary_file( - named=True, - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - delete=True, - delete_on_close=True, - loop=None, - executor=None, - max_size=0, - ): - """Async method to open a temporary file with async interface""" - if loop is None: - loop = asyncio.get_running_loop() - - if named: - cb = partial( - syncNamedTemporaryFile, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - delete=delete, - delete_on_close=delete_on_close, - ) - else: - cb = partial( - syncTemporaryFile, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - ) - - f = await loop.run_in_executor(executor, cb) - - # Wrap based on type of underlying IO object - if type(f) is syncTemporaryFileWrapper: - # _TemporaryFileWrapper was used (named files) - result = wrap(f.file, f, loop=loop, executor=executor) - result._closer = f._closer - return result - else: - # IO object was returned directly without wrapper - return wrap(f, f, loop=loop, executor=executor) - -else: - - async def _temporary_file( - named=True, - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - delete=True, - loop=None, - executor=None, - max_size=0, - ): - """Async method to open a temporary file with async interface""" - if loop is None: - loop = asyncio.get_running_loop() - - if named: - cb = partial( - syncNamedTemporaryFile, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - delete=delete, - ) - else: - cb = partial( - syncTemporaryFile, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - ) - - f = await loop.run_in_executor(executor, cb) - - # Wrap based on type of underlying IO object - if type(f) is syncTemporaryFileWrapper: - # _TemporaryFileWrapper was used (named files) - result = wrap(f.file, f, loop=loop, executor=executor) - # add delete property - result.delete = f.delete - return result - else: - # IO object was returned directly without wrapper - return wrap(f, f, loop=loop, executor=executor) - - -async def _spooled_temporary_file( - max_size=0, - mode="w+b", - buffering=-1, - encoding=None, - newline=None, - suffix=None, - prefix=None, - dir=None, - loop=None, - executor=None, -): - """Open a spooled temporary file with async interface""" - if loop is None: - loop = asyncio.get_running_loop() - - cb = partial( - syncSpooledTemporaryFile, - max_size=max_size, - mode=mode, - buffering=buffering, - encoding=encoding, - newline=newline, - suffix=suffix, - prefix=prefix, - dir=dir, - ) - - f = await loop.run_in_executor(executor, cb) - - # Single interface provided by SpooledTemporaryFile for all modes - return AsyncSpooledTemporaryFile(f, loop=loop, executor=executor) - - -async def _temporary_directory( - suffix=None, prefix=None, dir=None, loop=None, executor=None -): - """Async method to open a temporary directory with async interface""" - if loop is None: - loop = asyncio.get_running_loop() - - cb = partial(syncTemporaryDirectory, suffix, prefix, dir) - f = await loop.run_in_executor(executor, cb) - - return AsyncTemporaryDirectory(f, loop=loop, executor=executor) - - -class AiofilesContextManagerTempDir(AiofilesContextManager): - """With returns the directory location, not the object (matching sync lib)""" - - async def __aenter__(self): - self._obj = await self._coro - return self._obj.name - - -@singledispatch -def wrap(base_io_obj, file, *, loop=None, executor=None): - """Wrap the object with interface based on type of underlying IO""" - raise TypeError("Unsupported IO type: {}".format(base_io_obj)) - - -@wrap.register(TextIOBase) -def _(base_io_obj, file, *, loop=None, executor=None): - return AsyncTextIOWrapper(file, loop=loop, executor=executor) - - -@wrap.register(BufferedWriter) -def _(base_io_obj, file, *, loop=None, executor=None): - return AsyncBufferedIOBase(file, loop=loop, executor=executor) - - -@wrap.register(BufferedReader) -@wrap.register(BufferedRandom) -def _(base_io_obj, file, *, loop=None, executor=None): - return AsyncBufferedReader(file, loop=loop, executor=executor) - - -@wrap.register(FileIO) -def _(base_io_obj, file, *, loop=None, executor=None): - return AsyncFileIO(file, loop=loop, executor=executor) diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/temptypes.py b/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/temptypes.py deleted file mode 100644 index 1a1b1a8..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/tempfile/temptypes.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Async wrappers for spooled temp files and temp directory objects""" -from functools import partial - -from ..base import AsyncBase -from ..threadpool.utils import ( - cond_delegate_to_executor, - delegate_to_executor, - proxy_property_directly, -) - - -@delegate_to_executor("fileno", "rollover") -@cond_delegate_to_executor( - "close", - "flush", - "isatty", - "read", - "readline", - "readlines", - "seek", - "tell", - "truncate", -) -@proxy_property_directly("closed", "encoding", "mode", "name", "newlines") -class AsyncSpooledTemporaryFile(AsyncBase): - """Async wrapper for SpooledTemporaryFile class""" - - async def _check(self): - if self._file._rolled: - return - max_size = self._file._max_size - if max_size and self._file.tell() > max_size: - await self.rollover() - - async def write(self, s): - """Implementation to anticipate rollover""" - if self._file._rolled: - cb = partial(self._file.write, s) - return await self._loop.run_in_executor(self._executor, cb) - else: - file = self._file._file # reference underlying base IO object - rv = file.write(s) - await self._check() - return rv - - async def writelines(self, iterable): - """Implementation to anticipate rollover""" - if self._file._rolled: - cb = partial(self._file.writelines, iterable) - return await self._loop.run_in_executor(self._executor, cb) - else: - file = self._file._file # reference underlying base IO object - rv = file.writelines(iterable) - await self._check() - return rv - - -@delegate_to_executor("cleanup") -@proxy_property_directly("name") -class AsyncTemporaryDirectory: - """Async wrapper for TemporaryDirectory class""" - - def __init__(self, file, loop, executor): - self._file = file - self._loop = loop - self._executor = executor - - async def close(self): - await self.cleanup() diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/__init__.py b/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/__init__.py deleted file mode 100644 index e543283..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/__init__.py +++ /dev/null @@ -1,139 +0,0 @@ -"""Handle files using a thread pool executor.""" -import asyncio -import sys -from functools import partial, singledispatch -from io import ( - BufferedIOBase, - BufferedRandom, - BufferedReader, - BufferedWriter, - FileIO, - TextIOBase, -) - -from ..base import AiofilesContextManager -from .binary import ( - AsyncBufferedIOBase, - AsyncBufferedReader, - AsyncFileIO, - AsyncIndirectBufferedIOBase, -) -from .text import AsyncTextIndirectIOWrapper, AsyncTextIOWrapper - -sync_open = open - -__all__ = ( - "open", - "stdin", - "stdout", - "stderr", - "stdin_bytes", - "stdout_bytes", - "stderr_bytes", -) - - -def open( - file, - mode="r", - buffering=-1, - encoding=None, - errors=None, - newline=None, - closefd=True, - opener=None, - *, - loop=None, - executor=None, -): - return AiofilesContextManager( - _open( - file, - mode=mode, - buffering=buffering, - encoding=encoding, - errors=errors, - newline=newline, - closefd=closefd, - opener=opener, - loop=loop, - executor=executor, - ) - ) - - -async def _open( - file, - mode="r", - buffering=-1, - encoding=None, - errors=None, - newline=None, - closefd=True, - opener=None, - *, - loop=None, - executor=None, -): - """Open an asyncio file.""" - if loop is None: - loop = asyncio.get_running_loop() - cb = partial( - sync_open, - file, - mode=mode, - buffering=buffering, - encoding=encoding, - errors=errors, - newline=newline, - closefd=closefd, - opener=opener, - ) - f = await loop.run_in_executor(executor, cb) - - return wrap(f, loop=loop, executor=executor) - - -@singledispatch -def wrap(file, *, loop=None, executor=None): - raise TypeError("Unsupported io type: {}.".format(file)) - - -@wrap.register(TextIOBase) -def _(file, *, loop=None, executor=None): - return AsyncTextIOWrapper(file, loop=loop, executor=executor) - - -@wrap.register(BufferedWriter) -@wrap.register(BufferedIOBase) -def _(file, *, loop=None, executor=None): - return AsyncBufferedIOBase(file, loop=loop, executor=executor) - - -@wrap.register(BufferedReader) -@wrap.register(BufferedRandom) -def _(file, *, loop=None, executor=None): - return AsyncBufferedReader(file, loop=loop, executor=executor) - - -@wrap.register(FileIO) -def _(file, *, loop=None, executor=None): - return AsyncFileIO(file, loop=loop, executor=executor) - - -stdin = AsyncTextIndirectIOWrapper("sys.stdin", None, None, indirect=lambda: sys.stdin) -stdout = AsyncTextIndirectIOWrapper( - "sys.stdout", None, None, indirect=lambda: sys.stdout -) -stderr = AsyncTextIndirectIOWrapper( - "sys.stderr", None, None, indirect=lambda: sys.stderr -) -stdin_bytes = AsyncIndirectBufferedIOBase( - "sys.stdin.buffer", None, None, indirect=lambda: sys.stdin.buffer -) -stdout_bytes = AsyncIndirectBufferedIOBase( - "sys.stdout.buffer", None, None, indirect=lambda: sys.stdout.buffer -) -stderr_bytes = AsyncIndirectBufferedIOBase( - "sys.stderr.buffer", None, None, indirect=lambda: sys.stderr.buffer -) diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/binary.py b/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/binary.py deleted file mode 100644 index 63fcaff..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/binary.py +++ /dev/null @@ -1,104 +0,0 @@ -from ..base import AsyncBase, AsyncIndirectBase -from .utils import delegate_to_executor, proxy_method_directly, proxy_property_directly - - -@delegate_to_executor( - "close", - "flush", - "isatty", - "read", - "read1", - "readinto", - "readline", - "readlines", - "seek", - "seekable", - "tell", - "truncate", - "writable", - "write", - "writelines", -) -@proxy_method_directly("detach", "fileno", "readable") -@proxy_property_directly("closed", "raw", "name", "mode") -class AsyncBufferedIOBase(AsyncBase): - """The asyncio executor version of io.BufferedWriter and BufferedIOBase.""" - - -@delegate_to_executor("peek") -class AsyncBufferedReader(AsyncBufferedIOBase): - """The asyncio executor version of io.BufferedReader and Random.""" - - -@delegate_to_executor( - "close", - "flush", - "isatty", - "read", - "readall", - "readinto", - "readline", - "readlines", - "seek", - "seekable", - "tell", - "truncate", - "writable", - "write", - "writelines", -) -@proxy_method_directly("fileno", "readable") -@proxy_property_directly("closed", "name", "mode") -class AsyncFileIO(AsyncBase): - """The asyncio executor version of io.FileIO.""" - - -@delegate_to_executor( - "close", - "flush", - "isatty", - "read", - "read1", - "readinto", - "readline", - "readlines", - "seek", - "seekable", - "tell", - "truncate", - "writable", - "write", - "writelines", -) -@proxy_method_directly("detach", "fileno", "readable") -@proxy_property_directly("closed", "raw", "name", "mode") -class AsyncIndirectBufferedIOBase(AsyncIndirectBase): - """The indirect asyncio executor version of io.BufferedWriter and BufferedIOBase.""" - - -@delegate_to_executor("peek") -class AsyncIndirectBufferedReader(AsyncIndirectBufferedIOBase): - """The indirect asyncio executor version of io.BufferedReader and Random.""" - - -@delegate_to_executor( - "close", - "flush", - "isatty", - "read", - "readall", - "readinto", - "readline", - "readlines", - "seek", - "seekable", - "tell", - "truncate", - "writable", - "write", - "writelines", -) -@proxy_method_directly("fileno", "readable") -@proxy_property_directly("closed", "name", "mode") -class AsyncIndirectFileIO(AsyncIndirectBase): - """The indirect asyncio executor version of io.FileIO.""" diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/text.py b/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/text.py deleted file mode 100644 index 0e62590..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/text.py +++ /dev/null @@ -1,64 +0,0 @@ -from ..base import AsyncBase, AsyncIndirectBase -from .utils import delegate_to_executor, proxy_method_directly, proxy_property_directly - - -@delegate_to_executor( - "close", - "flush", - "isatty", - "read", - "readable", - "readline", - "readlines", - "seek", - "seekable", - "tell", - "truncate", - "write", - "writable", - "writelines", -) -@proxy_method_directly("detach", "fileno", "readable") -@proxy_property_directly( - "buffer", - "closed", - "encoding", - "errors", - "line_buffering", - "newlines", - "name", - "mode", -) -class AsyncTextIOWrapper(AsyncBase): - """The asyncio executor version of io.TextIOWrapper.""" - - -@delegate_to_executor( - "close", - "flush", - "isatty", - "read", - "readable", - "readline", - "readlines", - "seek", - "seekable", - "tell", - "truncate", - "write", - "writable", - "writelines", -) -@proxy_method_directly("detach", "fileno", "readable") -@proxy_property_directly( - "buffer", - "closed", - "encoding", - "errors", - "line_buffering", - "newlines", - "name", - "mode", -) -class AsyncTextIndirectIOWrapper(AsyncIndirectBase): - """The indirect asyncio executor version of io.TextIOWrapper.""" diff --git a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/utils.py b/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/utils.py deleted file mode 100644 index 5fd3bb9..0000000 --- a/serverenv/lib/python3.9/site-packages/aiofiles/threadpool/utils.py +++ /dev/null @@ -1,72 +0,0 @@ -import functools - - -def delegate_to_executor(*attrs): - def cls_builder(cls): - for attr_name in attrs: - setattr(cls, attr_name, _make_delegate_method(attr_name)) - return cls - - return cls_builder - - -def proxy_method_directly(*attrs): - def cls_builder(cls): - for attr_name in attrs: - setattr(cls, attr_name, _make_proxy_method(attr_name)) - return cls - - return cls_builder - - -def proxy_property_directly(*attrs): - def cls_builder(cls): - for attr_name in attrs: - setattr(cls, attr_name, _make_proxy_property(attr_name)) - return cls - - return cls_builder - - -def cond_delegate_to_executor(*attrs): - def cls_builder(cls): - for attr_name in attrs: - setattr(cls, attr_name, _make_cond_delegate_method(attr_name)) - return cls - - return cls_builder - - -def _make_delegate_method(attr_name): - async def method(self, *args, **kwargs): - cb = functools.partial(getattr(self._file, attr_name), *args, **kwargs) - return await self._loop.run_in_executor(self._executor, cb) - - return method - - -def _make_proxy_method(attr_name): - def method(self, *args, **kwargs): - return getattr(self._file, attr_name)(*args, **kwargs) - - return method - - -def _make_proxy_property(attr_name): - def proxy_property(self): - return getattr(self._file, attr_name) - - return property(proxy_property) - - -def _make_cond_delegate_method(attr_name): - """For spooled temp files, delegate only if rolled to file object""" - - async def method(self, *args, **kwargs): - if self._file._rolled: - cb = functools.partial(getattr(self._file, attr_name), *args, **kwargs) - return await self._loop.run_in_executor(self._executor, cb) - else: - return getattr(self._file, attr_name)(*args, **kwargs) - - return method diff --git a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/LICENSE.txt b/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/LICENSE.txt deleted file mode 100644 index 79c9825..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright 2010 Jason Kirtland - -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/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/METADATA deleted file mode 100644 index 6d343f5..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/METADATA +++ /dev/null @@ -1,60 +0,0 @@ -Metadata-Version: 2.3 -Name: blinker -Version: 1.9.0 -Summary: Fast, simple object-to-object and broadcast signaling -Author: Jason Kirtland -Maintainer-email: Pallets Ecosystem -Requires-Python: >=3.9 -Description-Content-Type: text/markdown -Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Typing :: Typed -Project-URL: Chat, https://discord.gg/pallets -Project-URL: Documentation, https://blinker.readthedocs.io -Project-URL: Source, https://github.com/pallets-eco/blinker/ - -# Blinker - -Blinker provides a fast dispatching system that allows any number of -interested parties to subscribe to events, or "signals". - - -## Pallets Community Ecosystem - -> [!IMPORTANT]\ -> This project is part of the Pallets Community Ecosystem. Pallets is the open -> source organization that maintains Flask; Pallets-Eco enables community -> maintenance of related projects. If you are interested in helping maintain -> this project, please reach out on [the Pallets Discord server][discord]. -> -> [discord]: https://discord.gg/pallets - - -## Example - -Signal receivers can subscribe to specific senders or receive signals -sent by any sender. - -```pycon ->>> from blinker import signal ->>> started = signal('round-started') ->>> def each(round): -... print(f"Round {round}") -... ->>> started.connect(each) - ->>> def round_two(round): -... print("This is round two.") -... ->>> started.connect(round_two, sender=2) - ->>> for round in range(1, 4): -... started.send(round) -... -Round 1! -Round 2! -This is round two. -Round 3! -``` - diff --git a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/RECORD deleted file mode 100644 index 2a56167..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/RECORD +++ /dev/null @@ -1,12 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/blinker/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/blinker/_utilities.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/blinker/base.cpython-39.pyc,, -blinker-1.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -blinker-1.9.0.dist-info/LICENSE.txt,sha256=nrc6HzhZekqhcCXSrhvjg5Ykx5XphdTw6Xac4p-spGc,1054 -blinker-1.9.0.dist-info/METADATA,sha256=uIRiM8wjjbHkCtbCyTvctU37IAZk0kEe5kxAld1dvzA,1633 -blinker-1.9.0.dist-info/RECORD,, -blinker-1.9.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 -blinker/__init__.py,sha256=I2EdZqpy4LyjX17Hn1yzJGWCjeLaVaPzsMgHkLfj_cQ,317 -blinker/_utilities.py,sha256=0J7eeXXTUx0Ivf8asfpx0ycVkp0Eqfqnj117x2mYX9E,1675 -blinker/base.py,sha256=QpDuvXXcwJF49lUBcH5BiST46Rz9wSG7VW_p7N_027M,19132 -blinker/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/WHEEL deleted file mode 100644 index e3c6fee..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker-1.9.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.10.1 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/blinker/__init__.py b/serverenv/lib/python3.9/site-packages/blinker/__init__.py deleted file mode 100644 index 1772fa4..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import annotations - -from .base import ANY -from .base import default_namespace -from .base import NamedSignal -from .base import Namespace -from .base import Signal -from .base import signal - -__all__ = [ - "ANY", - "default_namespace", - "NamedSignal", - "Namespace", - "Signal", - "signal", -] diff --git a/serverenv/lib/python3.9/site-packages/blinker/_utilities.py b/serverenv/lib/python3.9/site-packages/blinker/_utilities.py deleted file mode 100644 index 000c902..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker/_utilities.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import annotations - -import collections.abc as c -import inspect -import typing as t -from weakref import ref -from weakref import WeakMethod - -T = t.TypeVar("T") - - -class Symbol: - """A constant symbol, nicer than ``object()``. Repeated calls return the - same instance. - - >>> Symbol('foo') is Symbol('foo') - True - >>> Symbol('foo') - foo - """ - - symbols: t.ClassVar[dict[str, Symbol]] = {} - - def __new__(cls, name: str) -> Symbol: - if name in cls.symbols: - return cls.symbols[name] - - obj = super().__new__(cls) - cls.symbols[name] = obj - return obj - - def __init__(self, name: str) -> None: - self.name = name - - def __repr__(self) -> str: - return self.name - - def __getnewargs__(self) -> tuple[t.Any, ...]: - return (self.name,) - - -def make_id(obj: object) -> c.Hashable: - """Get a stable identifier for a receiver or sender, to be used as a dict - key or in a set. - """ - if inspect.ismethod(obj): - # The id of a bound method is not stable, but the id of the unbound - # function and instance are. - return id(obj.__func__), id(obj.__self__) - - if isinstance(obj, (str, int)): - # Instances with the same value always compare equal and have the same - # hash, even if the id may change. - return obj - - # Assume other types are not hashable but will always be the same instance. - return id(obj) - - -def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]: - if inspect.ismethod(obj): - return WeakMethod(obj, callback) # type: ignore[arg-type, return-value] - - return ref(obj, callback) diff --git a/serverenv/lib/python3.9/site-packages/blinker/base.py b/serverenv/lib/python3.9/site-packages/blinker/base.py deleted file mode 100644 index d051b94..0000000 --- a/serverenv/lib/python3.9/site-packages/blinker/base.py +++ /dev/null @@ -1,512 +0,0 @@ -from __future__ import annotations - -import collections.abc as c -import sys -import typing as t -import weakref -from collections import defaultdict -from contextlib import contextmanager -from functools import cached_property -from inspect import iscoroutinefunction - -from ._utilities import make_id -from ._utilities import make_ref -from ._utilities import Symbol - -F = t.TypeVar("F", bound=c.Callable[..., t.Any]) - -ANY = Symbol("ANY") -"""Symbol for "any sender".""" - -ANY_ID = 0 - - -class Signal: - """A notification emitter. - - :param doc: The docstring for the signal. - """ - - ANY = ANY - """An alias for the :data:`~blinker.ANY` sender symbol.""" - - set_class: type[set[t.Any]] = set - """The set class to use for tracking connected receivers and senders. - Python's ``set`` is unordered. If receivers must be dispatched in the order - they were connected, an ordered set implementation can be used. - - .. versionadded:: 1.7 - """ - - @cached_property - def receiver_connected(self) -> Signal: - """Emitted at the end of each :meth:`connect` call. - - The signal sender is the signal instance, and the :meth:`connect` - arguments are passed through: ``receiver``, ``sender``, and ``weak``. - - .. versionadded:: 1.2 - """ - return Signal(doc="Emitted after a receiver connects.") - - @cached_property - def receiver_disconnected(self) -> Signal: - """Emitted at the end of each :meth:`disconnect` call. - - The sender is the signal instance, and the :meth:`disconnect` arguments - are passed through: ``receiver`` and ``sender``. - - This signal is emitted **only** when :meth:`disconnect` is called - explicitly. This signal cannot be emitted by an automatic disconnect - when a weakly referenced receiver or sender goes out of scope, as the - instance is no longer be available to be used as the sender for this - signal. - - An alternative approach is available by subscribing to - :attr:`receiver_connected` and setting up a custom weakref cleanup - callback on weak receivers and senders. - - .. versionadded:: 1.2 - """ - return Signal(doc="Emitted after a receiver disconnects.") - - def __init__(self, doc: str | None = None) -> None: - if doc: - self.__doc__ = doc - - self.receivers: dict[ - t.Any, weakref.ref[c.Callable[..., t.Any]] | c.Callable[..., t.Any] - ] = {} - """The map of connected receivers. Useful to quickly check if any - receivers are connected to the signal: ``if s.receivers:``. The - structure and data is not part of the public API, but checking its - boolean value is. - """ - - self.is_muted: bool = False - self._by_receiver: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) - self._by_sender: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) - self._weak_senders: dict[t.Any, weakref.ref[t.Any]] = {} - - def connect(self, receiver: F, sender: t.Any = ANY, weak: bool = True) -> F: - """Connect ``receiver`` to be called when the signal is sent by - ``sender``. - - :param receiver: The callable to call when :meth:`send` is called with - the given ``sender``, passing ``sender`` as a positional argument - along with any extra keyword arguments. - :param sender: Any object or :data:`ANY`. ``receiver`` will only be - called when :meth:`send` is called with this sender. If ``ANY``, the - receiver will be called for any sender. A receiver may be connected - to multiple senders by calling :meth:`connect` multiple times. - :param weak: Track the receiver with a :mod:`weakref`. The receiver will - be automatically disconnected when it is garbage collected. When - connecting a receiver defined within a function, set to ``False``, - otherwise it will be disconnected when the function scope ends. - """ - receiver_id = make_id(receiver) - sender_id = ANY_ID if sender is ANY else make_id(sender) - - if weak: - self.receivers[receiver_id] = make_ref( - receiver, self._make_cleanup_receiver(receiver_id) - ) - else: - self.receivers[receiver_id] = receiver - - self._by_sender[sender_id].add(receiver_id) - self._by_receiver[receiver_id].add(sender_id) - - if sender is not ANY and sender_id not in self._weak_senders: - # store a cleanup for weakref-able senders - try: - self._weak_senders[sender_id] = make_ref( - sender, self._make_cleanup_sender(sender_id) - ) - except TypeError: - pass - - if "receiver_connected" in self.__dict__ and self.receiver_connected.receivers: - try: - self.receiver_connected.send( - self, receiver=receiver, sender=sender, weak=weak - ) - except TypeError: - # TODO no explanation or test for this - self.disconnect(receiver, sender) - raise - - return receiver - - def connect_via(self, sender: t.Any, weak: bool = False) -> c.Callable[[F], F]: - """Connect the decorated function to be called when the signal is sent - by ``sender``. - - The decorated function will be called when :meth:`send` is called with - the given ``sender``, passing ``sender`` as a positional argument along - with any extra keyword arguments. - - :param sender: Any object or :data:`ANY`. ``receiver`` will only be - called when :meth:`send` is called with this sender. If ``ANY``, the - receiver will be called for any sender. A receiver may be connected - to multiple senders by calling :meth:`connect` multiple times. - :param weak: Track the receiver with a :mod:`weakref`. The receiver will - be automatically disconnected when it is garbage collected. When - connecting a receiver defined within a function, set to ``False``, - otherwise it will be disconnected when the function scope ends.= - - .. versionadded:: 1.1 - """ - - def decorator(fn: F) -> F: - self.connect(fn, sender, weak) - return fn - - return decorator - - @contextmanager - def connected_to( - self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY - ) -> c.Generator[None, None, None]: - """A context manager that temporarily connects ``receiver`` to the - signal while a ``with`` block executes. When the block exits, the - receiver is disconnected. Useful for tests. - - :param receiver: The callable to call when :meth:`send` is called with - the given ``sender``, passing ``sender`` as a positional argument - along with any extra keyword arguments. - :param sender: Any object or :data:`ANY`. ``receiver`` will only be - called when :meth:`send` is called with this sender. If ``ANY``, the - receiver will be called for any sender. - - .. versionadded:: 1.1 - """ - self.connect(receiver, sender=sender, weak=False) - - try: - yield None - finally: - self.disconnect(receiver) - - @contextmanager - def muted(self) -> c.Generator[None, None, None]: - """A context manager that temporarily disables the signal. No receivers - will be called if the signal is sent, until the ``with`` block exits. - Useful for tests. - """ - self.is_muted = True - - try: - yield None - finally: - self.is_muted = False - - def send( - self, - sender: t.Any | None = None, - /, - *, - _async_wrapper: c.Callable[ - [c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]], c.Callable[..., t.Any] - ] - | None = None, - **kwargs: t.Any, - ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: - """Call all receivers that are connected to the given ``sender`` - or :data:`ANY`. Each receiver is called with ``sender`` as a positional - argument along with any extra keyword arguments. Return a list of - ``(receiver, return value)`` tuples. - - The order receivers are called is undefined, but can be influenced by - setting :attr:`set_class`. - - If a receiver raises an exception, that exception will propagate up. - This makes debugging straightforward, with an assumption that correctly - implemented receivers will not raise. - - :param sender: Call receivers connected to this sender, in addition to - those connected to :data:`ANY`. - :param _async_wrapper: Will be called on any receivers that are async - coroutines to turn them into sync callables. For example, could run - the receiver with an event loop. - :param kwargs: Extra keyword arguments to pass to each receiver. - - .. versionchanged:: 1.7 - Added the ``_async_wrapper`` argument. - """ - if self.is_muted: - return [] - - results = [] - - for receiver in self.receivers_for(sender): - if iscoroutinefunction(receiver): - if _async_wrapper is None: - raise RuntimeError("Cannot send to a coroutine function.") - - result = _async_wrapper(receiver)(sender, **kwargs) - else: - result = receiver(sender, **kwargs) - - results.append((receiver, result)) - - return results - - async def send_async( - self, - sender: t.Any | None = None, - /, - *, - _sync_wrapper: c.Callable[ - [c.Callable[..., t.Any]], c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]] - ] - | None = None, - **kwargs: t.Any, - ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: - """Await all receivers that are connected to the given ``sender`` - or :data:`ANY`. Each receiver is called with ``sender`` as a positional - argument along with any extra keyword arguments. Return a list of - ``(receiver, return value)`` tuples. - - The order receivers are called is undefined, but can be influenced by - setting :attr:`set_class`. - - If a receiver raises an exception, that exception will propagate up. - This makes debugging straightforward, with an assumption that correctly - implemented receivers will not raise. - - :param sender: Call receivers connected to this sender, in addition to - those connected to :data:`ANY`. - :param _sync_wrapper: Will be called on any receivers that are sync - callables to turn them into async coroutines. For example, - could call the receiver in a thread. - :param kwargs: Extra keyword arguments to pass to each receiver. - - .. versionadded:: 1.7 - """ - if self.is_muted: - return [] - - results = [] - - for receiver in self.receivers_for(sender): - if not iscoroutinefunction(receiver): - if _sync_wrapper is None: - raise RuntimeError("Cannot send to a non-coroutine function.") - - result = await _sync_wrapper(receiver)(sender, **kwargs) - else: - result = await receiver(sender, **kwargs) - - results.append((receiver, result)) - - return results - - def has_receivers_for(self, sender: t.Any) -> bool: - """Check if there is at least one receiver that will be called with the - given ``sender``. A receiver connected to :data:`ANY` will always be - called, regardless of sender. Does not check if weakly referenced - receivers are still live. See :meth:`receivers_for` for a stronger - search. - - :param sender: Check for receivers connected to this sender, in addition - to those connected to :data:`ANY`. - """ - if not self.receivers: - return False - - if self._by_sender[ANY_ID]: - return True - - if sender is ANY: - return False - - return make_id(sender) in self._by_sender - - def receivers_for( - self, sender: t.Any - ) -> c.Generator[c.Callable[..., t.Any], None, None]: - """Yield each receiver to be called for ``sender``, in addition to those - to be called for :data:`ANY`. Weakly referenced receivers that are not - live will be disconnected and skipped. - - :param sender: Yield receivers connected to this sender, in addition - to those connected to :data:`ANY`. - """ - # TODO: test receivers_for(ANY) - if not self.receivers: - return - - sender_id = make_id(sender) - - if sender_id in self._by_sender: - ids = self._by_sender[ANY_ID] | self._by_sender[sender_id] - else: - ids = self._by_sender[ANY_ID].copy() - - for receiver_id in ids: - receiver = self.receivers.get(receiver_id) - - if receiver is None: - continue - - if isinstance(receiver, weakref.ref): - strong = receiver() - - if strong is None: - self._disconnect(receiver_id, ANY_ID) - continue - - yield strong - else: - yield receiver - - def disconnect(self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY) -> None: - """Disconnect ``receiver`` from being called when the signal is sent by - ``sender``. - - :param receiver: A connected receiver callable. - :param sender: Disconnect from only this sender. By default, disconnect - from all senders. - """ - sender_id: c.Hashable - - if sender is ANY: - sender_id = ANY_ID - else: - sender_id = make_id(sender) - - receiver_id = make_id(receiver) - self._disconnect(receiver_id, sender_id) - - if ( - "receiver_disconnected" in self.__dict__ - and self.receiver_disconnected.receivers - ): - self.receiver_disconnected.send(self, receiver=receiver, sender=sender) - - def _disconnect(self, receiver_id: c.Hashable, sender_id: c.Hashable) -> None: - if sender_id == ANY_ID: - if self._by_receiver.pop(receiver_id, None) is not None: - for bucket in self._by_sender.values(): - bucket.discard(receiver_id) - - self.receivers.pop(receiver_id, None) - else: - self._by_sender[sender_id].discard(receiver_id) - self._by_receiver[receiver_id].discard(sender_id) - - def _make_cleanup_receiver( - self, receiver_id: c.Hashable - ) -> c.Callable[[weakref.ref[c.Callable[..., t.Any]]], None]: - """Create a callback function to disconnect a weakly referenced - receiver when it is garbage collected. - """ - - def cleanup(ref: weakref.ref[c.Callable[..., t.Any]]) -> None: - # If the interpreter is shutting down, disconnecting can result in a - # weird ignored exception. Don't call it in that case. - if not sys.is_finalizing(): - self._disconnect(receiver_id, ANY_ID) - - return cleanup - - def _make_cleanup_sender( - self, sender_id: c.Hashable - ) -> c.Callable[[weakref.ref[t.Any]], None]: - """Create a callback function to disconnect all receivers for a weakly - referenced sender when it is garbage collected. - """ - assert sender_id != ANY_ID - - def cleanup(ref: weakref.ref[t.Any]) -> None: - self._weak_senders.pop(sender_id, None) - - for receiver_id in self._by_sender.pop(sender_id, ()): - self._by_receiver[receiver_id].discard(sender_id) - - return cleanup - - def _cleanup_bookkeeping(self) -> None: - """Prune unused sender/receiver bookkeeping. Not threadsafe. - - Connecting & disconnecting leaves behind a small amount of bookkeeping - data. Typical workloads using Blinker, for example in most web apps, - Flask, CLI scripts, etc., are not adversely affected by this - bookkeeping. - - With a long-running process performing dynamic signal routing with high - volume, e.g. connecting to function closures, senders are all unique - object instances. Doing all of this over and over may cause memory usage - to grow due to extraneous bookkeeping. (An empty ``set`` for each stale - sender/receiver pair.) - - This method will prune that bookkeeping away, with the caveat that such - pruning is not threadsafe. The risk is that cleanup of a fully - disconnected receiver/sender pair occurs while another thread is - connecting that same pair. If you are in the highly dynamic, unique - receiver/sender situation that has lead you to this method, that failure - mode is perhaps not a big deal for you. - """ - for mapping in (self._by_sender, self._by_receiver): - for ident, bucket in list(mapping.items()): - if not bucket: - mapping.pop(ident, None) - - def _clear_state(self) -> None: - """Disconnect all receivers and senders. Useful for tests.""" - self._weak_senders.clear() - self.receivers.clear() - self._by_sender.clear() - self._by_receiver.clear() - - -class NamedSignal(Signal): - """A named generic notification emitter. The name is not used by the signal - itself, but matches the key in the :class:`Namespace` that it belongs to. - - :param name: The name of the signal within the namespace. - :param doc: The docstring for the signal. - """ - - def __init__(self, name: str, doc: str | None = None) -> None: - super().__init__(doc) - - #: The name of this signal. - self.name: str = name - - def __repr__(self) -> str: - base = super().__repr__() - return f"{base[:-1]}; {self.name!r}>" # noqa: E702 - - -class Namespace(dict[str, NamedSignal]): - """A dict mapping names to signals.""" - - def signal(self, name: str, doc: str | None = None) -> NamedSignal: - """Return the :class:`NamedSignal` for the given ``name``, creating it - if required. Repeated calls with the same name return the same signal. - - :param name: The name of the signal. - :param doc: The docstring of the signal. - """ - if name not in self: - self[name] = NamedSignal(name, doc) - - return self[name] - - -class _PNamespaceSignal(t.Protocol): - def __call__(self, name: str, doc: str | None = None) -> NamedSignal: ... - - -default_namespace: Namespace = Namespace() -"""A default :class:`Namespace` for creating named signals. :func:`signal` -creates a :class:`NamedSignal` in this namespace. -""" - -signal: _PNamespaceSignal = default_namespace.signal -"""Return a :class:`NamedSignal` in :data:`default_namespace` with the given -``name``, creating it if required. Repeated calls with the same name return the -same signal. -""" diff --git a/serverenv/lib/python3.9/site-packages/blinker/py.typed b/serverenv/lib/python3.9/site-packages/blinker/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/LICENSE.txt b/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/LICENSE.txt deleted file mode 100644 index d12a849..0000000 --- a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/METADATA deleted file mode 100644 index 366d1a7..0000000 --- a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/METADATA +++ /dev/null @@ -1,74 +0,0 @@ -Metadata-Version: 2.3 -Name: click -Version: 8.1.8 -Summary: Composable command line interface toolkit -Maintainer-email: Pallets -Requires-Python: >=3.7 -Description-Content-Type: text/markdown -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Typing :: Typed -Requires-Dist: colorama; platform_system == 'Windows' -Requires-Dist: importlib-metadata; python_version < '3.8' -Project-URL: Changes, https://click.palletsprojects.com/changes/ -Project-URL: Chat, https://discord.gg/pallets -Project-URL: Documentation, https://click.palletsprojects.com/ -Project-URL: Donate, https://palletsprojects.com/donate -Project-URL: Source, https://github.com/pallets/click/ - -# $ click_ - -Click is a Python package for creating beautiful command line interfaces -in a composable way with as little code as necessary. It's the "Command -Line Interface Creation Kit". It's highly configurable but comes with -sensible defaults out of the box. - -It aims to make the process of writing command line tools quick and fun -while also preventing any frustration caused by the inability to -implement an intended CLI API. - -Click in three points: - -- Arbitrary nesting of commands -- Automatic help page generation -- Supports lazy loading of subcommands at runtime - - -## A Simple Example - -```python -import click - -@click.command() -@click.option("--count", default=1, help="Number of greetings.") -@click.option("--name", prompt="Your name", help="The person to greet.") -def hello(count, name): - """Simple program that greets NAME for a total of COUNT times.""" - for _ in range(count): - click.echo(f"Hello, {name}!") - -if __name__ == '__main__': - hello() -``` - -``` -$ python hello.py --count=3 -Your name: Click -Hello, Click! -Hello, Click! -Hello, Click! -``` - - -## Donate - -The Pallets organization develops and supports Click and other popular -packages. In order to grow the community of contributors and users, and -allow the maintainers to devote more time to the projects, [please -donate today][]. - -[please donate today]: https://palletsprojects.com/donate - diff --git a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/RECORD deleted file mode 100644 index 78628e1..0000000 --- a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/RECORD +++ /dev/null @@ -1,38 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/_compat.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/_termui_impl.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/_textwrap.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/_winconsole.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/core.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/decorators.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/exceptions.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/formatting.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/globals.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/parser.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/shell_completion.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/termui.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/testing.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/types.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/click/utils.cpython-39.pyc,, -click-8.1.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -click-8.1.8.dist-info/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 -click-8.1.8.dist-info/METADATA,sha256=WJtQ6uGS2ybLfvUE4vC0XIhIBr4yFGwjrMBR2fiCQ-Q,2263 -click-8.1.8.dist-info/RECORD,, -click-8.1.8.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 -click/__init__.py,sha256=j1DJeCbga4ribkv5uyvIAzI0oFN13fW9mevDKShFelo,3188 -click/_compat.py,sha256=IGKh_J5QdfKELitnRfTGHneejWxoCw_NX9tfMbdcg3w,18730 -click/_termui_impl.py,sha256=a5z7I9gOFeMmu7Gb6_RPyQ8GPuVP1EeblixcWSPSQPk,24783 -click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 -click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 -click/core.py,sha256=Q1nEVdctZwvIPOlt4vfHko0TYnHCeE40UEEul8Wpyvs,114748 -click/decorators.py,sha256=7t6F-QWowtLh6F_6l-4YV4Y4yNTcqFQEu9i37zIz68s,18925 -click/exceptions.py,sha256=V7zDT6emqJ8iNl0kF1P5kpFmLMWQ1T1L7aNNKM4YR0w,9600 -click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 -click/globals.py,sha256=cuJ6Bbo073lgEEmhjr394PeM-QFmXM-Ci-wmfsd7H5g,1954 -click/parser.py,sha256=h4sndcpF5OHrZQN8vD8IWb5OByvW7ABbhRToxovrqS8,19067 -click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -click/shell_completion.py,sha256=TR0dXEGcvWb9Eo3aaQEXGhnvNS3FF4H4QcuLnvAvYo4,18636 -click/termui.py,sha256=dLxiS70UOvIYBda_nEEZaPAFOVDVmRs1sEPMuLDowQo,28310 -click/testing.py,sha256=3RA8anCf7TZ8-5RAF5it2Te-aWXBAL5VLasQnMiC2ZQ,16282 -click/types.py,sha256=BD5Qqq4h-8kawBmOIzJlmq4xzThAf4wCvaOLZSBDNx0,36422 -click/utils.py,sha256=ce-IrO9ilII76LGkU354pOdHbepM8UftfNH7SfMU_28,20330 diff --git a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/WHEEL deleted file mode 100644 index e3c6fee..0000000 --- a/serverenv/lib/python3.9/site-packages/click-8.1.8.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.10.1 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/click/__init__.py b/serverenv/lib/python3.9/site-packages/click/__init__.py deleted file mode 100644 index 2610d0e..0000000 --- a/serverenv/lib/python3.9/site-packages/click/__init__.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -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 HelpOption as HelpOption -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.8" diff --git a/serverenv/lib/python3.9/site-packages/click/_compat.py b/serverenv/lib/python3.9/site-packages/click/_compat.py deleted file mode 100644 index 9153d15..0000000 --- a/serverenv/lib/python3.9/site-packages/click/_compat.py +++ /dev/null @@ -1,623 +0,0 @@ -import codecs -import io -import os -import re -import sys -import typing as t -from weakref import WeakKeyDictionary - -CYGWIN = sys.platform.startswith("cygwin") -WIN = sys.platform.startswith("win") -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 _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[t.Any]) -> str: - """Returns the default stream encoding if not found.""" - rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() - if is_ascii_encoding(rv): - return "utf-8" - return rv - - -class _NonClosingTextIOWrapper(io.TextIOWrapper): - def __init__( - self, - stream: t.BinaryIO, - encoding: 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[t.Any], default: bool = False) -> bool: - try: - return isinstance(stream.read(0), bytes) - except Exception: - return default - # This happens in some cases where the stream was already - # closed. In this case, we assume the default. - - -def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: - try: - stream.write(b"") - except Exception: - try: - stream.write("") - return False - except Exception: - pass - return default - return True - - -def _find_binary_reader(stream: t.IO[t.Any]) -> t.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.Any]) -> 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[t.Any], - encoding: t.Optional[str], - errors: t.Optional[str], - is_binary: t.Callable[[t.IO[t.Any], bool], bool], - find_binary: t.Callable[[t.IO[t.Any]], 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[t.Any], - 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[t.Any], - 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[str]", int], - mode: str, - encoding: t.Optional[str], - errors: t.Optional[str], -) -> t.IO[t.Any]: - """Handles not passing ``encoding`` and ``errors`` in binary mode.""" - if "b" in mode: - return open(file, mode) - - return open(file, mode, encoding=encoding, errors=errors) - - -def open_stream( - filename: "t.Union[str, os.PathLike[str]]", - mode: str = "r", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", - atomic: bool = False, -) -> t.Tuple[t.IO[t.Any], bool]: - binary = "b" in mode - filename = os.fspath(filename) - - # Standard streams first. These are simple because they ignore the - # atomic flag. Use fsdecode to handle Path("-"). - if os.fsdecode(filename) == "-": - if any(m in mode for m in ["w", "a", "x"]): - if binary: - return get_binary_stdout(), False - return get_text_stdout(encoding=encoding, errors=errors), False - if binary: - return get_binary_stdin(), False - return get_text_stdin(encoding=encoding, errors=errors), False - - # Non-atomic writes directly go out through the regular open functions. - if not atomic: - return _wrap_io_open(filename, mode, encoding, errors), True - - # Some usability stuff for atomic writes - if "a" in mode: - raise ValueError( - "Appending to an existing file is not supported, because that" - " would involve an expensive `copy`-operation to a temporary" - " file. Open the file in normal `w`-mode and copy explicitly" - " if that's what you're after." - ) - if "x" in mode: - raise ValueError("Use the `overwrite`-parameter instead.") - if "w" not in mode: - raise ValueError("Atomic writes only make sense with `w`-mode.") - - # Atomic writes are more complicated. They work by opening a file - # as a proxy in the same folder and then using the fdopen - # functionality to wrap it in a Python file. Then we wrap it in an - # atomic file that moves the file over on close. - import errno - import random - - try: - perm: 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[t.Any], af), True - - -class _AtomicFile: - def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: - self._f = f - self._tmp_filename = tmp_filename - self._real_filename = real_filename - self.closed = False - - @property - def name(self) -> str: - return self._real_filename - - def close(self, delete: bool = False) -> None: - if self.closed: - return - self._f.close() - os.replace(self._tmp_filename, self._real_filename) - self.closed = True - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._f, name) - - def __enter__(self) -> "_AtomicFile": - return self - - def __exit__(self, exc_type: t.Optional[t.Type[BaseException]], *_: t.Any) -> None: - self.close(delete=exc_type is not None) - - def __repr__(self) -> str: - return repr(self._f) - - -def strip_ansi(value: str) -> str: - return _ansi_re.sub("", value) - - -def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: - while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): - stream = stream._stream - - return stream.__class__.__module__.startswith("ipykernel.") - - -def should_strip_ansi( - stream: t.Optional[t.IO[t.Any]] = 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 sys.getfilesystemencoding() - - 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[t.Any]) -> bool: - try: - return stream.isatty() - except Exception: - return False - - -def _make_cached_stream_func( - src_func: t.Callable[[], t.Optional[t.TextIO]], - wrapper_func: t.Callable[[], t.TextIO], -) -> t.Callable[[], t.Optional[t.TextIO]]: - cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() - - def func() -> t.Optional[t.TextIO]: - stream = src_func() - - if stream is None: - return None - - try: - rv = cache.get(stream) - except Exception: - rv = None - if rv is not None: - return rv - rv = wrapper_func() - try: - cache[stream] = rv - except Exception: - pass - return rv - - return func - - -_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) -_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) -_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) - - -binary_streams: 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/serverenv/lib/python3.9/site-packages/click/_termui_impl.py b/serverenv/lib/python3.9/site-packages/click/_termui_impl.py deleted file mode 100644 index ad9f8f6..0000000 --- a/serverenv/lib/python3.9/site-packages/click/_termui_impl.py +++ /dev/null @@ -1,788 +0,0 @@ -""" -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 io import StringIO -from shutil import which -from types import TracebackType - -from ._compat import _default_text_stdout -from ._compat import CYGWIN -from ._compat import get_best_encoding -from ._compat import isatty -from ._compat import open_stream -from ._compat import strip_ansi -from ._compat import term_len -from ._compat import WIN -from .exceptions import ClickException -from .utils import echo - -V = t.TypeVar("V") - -if os.name == "nt": - BEFORE_BAR = "\r" - AFTER_BAR = "\n" -else: - BEFORE_BAR = "\r\033[?25l" - AFTER_BAR = "\033[?25h\n" - - -class ProgressBar(t.Generic[V]): - def __init__( - self, - iterable: 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: str = label or "" - - if file is None: - file = _default_text_stdout() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if file is None: - file = StringIO() - - self.file = file - self.color = color - self.update_min_steps = update_min_steps - self._completed_intervals = 0 - self.width: int = width - self.autowidth: bool = width == 0 - - if length is None: - from operator import length_hint - - length = length_hint(iterable, -1) - - if length == -1: - length = None - if iterable is None: - if length is None: - raise TypeError("iterable or length is required") - iterable = t.cast(t.Iterable[V], range(length)) - self.iter: t.Iterable[V] = iter(iterable) - self.length = length - self.pos = 0 - self.avg: t.List[float] = [] - self.last_eta: float - self.start: float - self.start = self.last_eta = time.time() - self.eta_known: bool = False - self.finished: bool = False - self.max_width: t.Optional[int] = None - self.entered: bool = False - self.current_item: t.Optional[V] = None - self.is_hidden: bool = not isatty(self.file) - self._last_line: t.Optional[str] = None - - def __enter__(self) -> "ProgressBar[V]": - self.entered = True - self.render_progress() - return self - - def __exit__( - self, - exc_type: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - 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() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if stdout is None: - stdout = StringIO() - - if not isatty(sys.stdin) or not isatty(stdout): - return _nullpager(stdout, generator, color) - pager_cmd = (os.environ.get("PAGER", None) or "").strip() - if pager_cmd: - if WIN: - if _tempfilepager(generator, pager_cmd, color): - return - elif _pipepager(generator, pager_cmd, color): - return - if os.environ.get("TERM") in ("dumb", "emacs"): - return _nullpager(stdout, generator, color) - if (WIN or sys.platform.startswith("os2")) and _tempfilepager( - generator, "more", color - ): - return - if _pipepager(generator, "less", color): - return - - import tempfile - - fd, filename = tempfile.mkstemp() - os.close(fd) - try: - if _pipepager(generator, "more", color): - return - return _nullpager(stdout, generator, color) - finally: - os.unlink(filename) - - -def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> bool: - """Page through text by feeding it to another program. Invoking a - pager through this might support colors. - - Returns True if the command was found, False otherwise and thus another - pager should be attempted. - """ - cmd_absolute = which(cmd) - if cmd_absolute is None: - return False - - 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_absolute], - shell=True, - stdin=subprocess.PIPE, - env=env, - errors="replace", - text=True, - ) - assert c.stdin is not None - try: - for text in generator: - if not color: - text = strip_ansi(text) - - c.stdin.write(text) - except (OSError, KeyboardInterrupt): - pass - else: - c.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 - - return True - - -def _tempfilepager( - generator: t.Iterable[str], - cmd: str, - color: t.Optional[bool], -) -> bool: - """Page through text by invoking a program on a temporary file. - - Returns True if the command was found, False otherwise and thus another - pager should be attempted. - """ - # Which is necessary for Windows, it is also recommended in the Popen docs. - cmd_absolute = which(cmd) - if cmd_absolute is None: - return False - - import subprocess - import tempfile - - fd, filename = tempfile.mkstemp() - # TODO: This never terminates if the passed generator never terminates. - text = "".join(generator) - if not color: - text = strip_ansi(text) - encoding = get_best_encoding(sys.stdout) - with open_stream(filename, "wb")[0] as f: - f.write(text.encode(encoding)) - try: - subprocess.call([cmd_absolute, filename]) - except OSError: - # Command not found - pass - finally: - os.close(fd) - os.unlink(filename) - - return True - - -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 which(editor) is not None: - 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) - args = ["explorer", f"/select,{url}"] - else: - args = ["start"] - if wait: - args.append("/WAIT") - args.append("") - args.append(url) - try: - return subprocess.call(args) - except OSError: - # Command not found - return 127 - elif CYGWIN: - if locate: - url = _unquote_file(url) - args = ["cygstart", os.path.dirname(url)] - else: - args = ["cygstart"] - if wait: - args.append("-w") - args.append(url) - try: - return subprocess.call(args) - except OSError: - # Command not found - return 127 - - try: - if locate: - url = os.path.dirname(_unquote_file(url)) or "." - else: - url = _unquote_file(url) - c = subprocess.Popen(["xdg-open", url]) - if wait: - return c.wait() - return 0 - except OSError: - if url.startswith(("http://", "https://")) and not locate and not wait: - import webbrowser - - webbrowser.open(url) - return 0 - return 1 - - -def _translate_ch_to_exc(ch: str) -> 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 termios - import tty - - @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/serverenv/lib/python3.9/site-packages/click/_textwrap.py b/serverenv/lib/python3.9/site-packages/click/_textwrap.py deleted file mode 100644 index b47dcbd..0000000 --- a/serverenv/lib/python3.9/site-packages/click/_textwrap.py +++ /dev/null @@ -1,49 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/click/_winconsole.py b/serverenv/lib/python3.9/site-packages/click/_winconsole.py deleted file mode 100644 index 6b20df3..0000000 --- a/serverenv/lib/python3.9/site-packages/click/_winconsole.py +++ /dev/null @@ -1,279 +0,0 @@ -# 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/serverenv/lib/python3.9/site-packages/click/core.py b/serverenv/lib/python3.9/site-packages/click/core.py deleted file mode 100644 index e630501..0000000 --- a/serverenv/lib/python3.9/site-packages/click/core.py +++ /dev/null @@ -1,3047 +0,0 @@ -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 update_wrapper -from gettext import gettext as _ -from gettext import ngettext -from itertools import repeat -from types import TracebackType - -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 .decorators import HelpOption - 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"]: - """Returns all declared parameters in the order they should be processed. - - The declared parameters are re-shuffled depending on the order in which - they were invoked, as well as the eagerness of each parameters. - - The invocation order takes precedence over the declaration order. I.e. the - order in which the user provided them to the CLI is respected. - - This behavior and its effect on callback evaluation is detailed at: - https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order - """ - - def sort_key(item: "Parameter") -> 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.MutableMapping[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.MutableMapping[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: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - 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) - - @t.overload - def invoke( - __self, - __callback: "t.Callable[..., V]", - *args: t.Any, - **kwargs: t.Any, - ) -> V: ... - - @t.overload - def invoke( - __self, - __callback: "Command", - *args: t.Any, - **kwargs: t.Any, - ) -> t.Any: ... - - def invoke( - __self, - __callback: t.Union["Command", "t.Callable[..., V]"], - *args: t.Any, - **kwargs: t.Any, - ) -> t.Union[t.Any, V]: - """Invokes a command callback in exactly the way it expects. There - are two ways to invoke this method: - - 1. the first argument can be a callback and all other arguments and - keyword arguments are forwarded directly to the function. - 2. the first argument is a click command object. In that case all - arguments are forwarded as well but proper click parameters - (options and click arguments) must be keyword arguments and Click - will fill in defaults. - - 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 = t.cast("t.Callable[..., V]", other_cmd.callback) - - ctx = __self._make_sub_context(other_cmd) - - for param in other_cmd.params: - if param.name not in kwargs and param.expose_value: - kwargs[param.name] = param.type_cast_value( # type: ignore - ctx, param.get_default(ctx) - ) - - # Track all kwargs as params, so that forward() will pass - # them on in subsequent calls. - ctx.params.update(kwargs) - else: - ctx = __self - - with augment_usage_errors(__self): - with ctx: - return __callback(*args, **kwargs) - - def forward(__self, __cmd: "Command", *args: t.Any, **kwargs: t.Any) -> t.Any: - """Similar to :meth:`invoke` but fills in default keyword - arguments from the current context if the other command expects - it. This cannot invoke callbacks directly, only other commands. - - .. versionchanged:: 8.0 - All ``kwargs`` are tracked in :attr:`params` so they will be - passed if ``forward`` is called at multiple levels. - """ - # Can only forward to other commands, not direct callbacks. - if not isinstance(__cmd, Command): - raise TypeError("Callback is not a command.") - - for param in __self.params: - if param not in kwargs: - kwargs[param] = __self.params[param] - - return __self.invoke(__cmd, *args, **kwargs) - - def set_parameter_source(self, name: str, source: ParameterSource) -> None: - """Set the source of a parameter. This indicates the location - from which the value of the parameter was obtained. - - :param name: The name of the parameter. - :param source: A member of :class:`~click.core.ParameterSource`. - """ - self._parameter_source[name] = source - - def get_parameter_source(self, name: str) -> 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.MutableMapping[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.MutableMapping[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'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, # type: ignore[arg-type] - info_name=info_name, - parent=parent, - **extra, - ) - - with ctx.scope(cleanup=False): - self.parse_args(ctx, args) - return ctx - - def parse_args(self, ctx: Context, args: 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 invocable 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) as e: - echo(file=sys.stderr) - raise Abort() from e - except ClickException as e: - if not standalone_mode: - raise - e.show() - sys.exit(e.exit_code) - except OSError as e: - if e.errno == errno.EPIPE: - sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) - sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) - sys.exit(1) - else: - raise - except Exit as e: - if standalone_mode: - sys.exit(e.exit_code) - else: - # in non-standalone mode, return the exit code - # note that this is only reached if `self.invoke` above raises - # an Exit explicitly -- thus bypassing the check there which - # would return its result - # the results of non-standalone execution may therefore be - # somewhat ambiguous: if there are codepaths which lead to - # `ctx.exit(1)` and to `return 1`, the caller won't be able to - # tell the difference between the two - return e.exit_code - except Abort: - if not standalone_mode: - raise - echo(_("Aborted!"), file=sys.stderr) - sys.exit(1) - - def _main_shell_completion( - self, - ctx_args: t.MutableMapping[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``. - - .. versionchanged:: 8.2.0 - Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). - """ - if complete_var is None: - complete_name = prog_name.replace("-", "_").replace(".", "_") - complete_var = f"_{complete_name}_COMPLETE".upper() - - instruction = os.environ.get(complete_var) - - if not instruction: - return - - from .shell_completion import shell_complete - - rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) - sys.exit(rv) - - def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: - """Alias for :meth:`main`.""" - return self.main(*args, **kwargs) - - -class 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.MutableMapping[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._help_option: t.Optional[HelpOption] = None - 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. - - Unless ``add_help_option`` is ``False``. - - .. versionchanged:: 8.1.8 - The help option is now cached to avoid creating it multiple times. - """ - help_options = self.get_help_option_names(ctx) - - if not help_options or not self.add_help_option: - return None - - # Cache the help option object in private _help_option attribute to - # avoid creating it multiple times. Not doing this will break the - # callback odering by iter_params_for_processing(), which relies on - # object comparison. - if self._help_option is None: - # Avoid circular import. - from .decorators import HelpOption - - self._help_option = HelpOption(help_options) - - return self._help_option - - def make_parser(self, ctx: Context) -> OptionParser: - """Creates the underlying option parser for this command.""" - parser = OptionParser(ctx) - for param in self.get_params(ctx): - param.add_to_parser(parser, ctx) - return parser - - def get_help(self, ctx: Context) -> str: - """Formats the help into a string and returns it. - - Calls :meth:`format_help` internally. - """ - formatter = ctx.make_formatter() - self.format_help(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - def get_short_help_str(self, limit: int = 45) -> str: - """Gets short help for the command or makes it by shortening the - long help string. - """ - if self.short_help: - text = inspect.cleandoc(self.short_help) - elif self.help: - text = make_default_short_help(self.help, limit) - else: - text = "" - - if self.deprecated: - 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.""" - if self.help is not None: - # truncate the help text to the first form feed - text = inspect.cleandoc(self.help).partition("\f")[0] - else: - text = "" - - if self.deprecated: - text = _("(Deprecated) {text}").format(text=text) - - if text: - formatter.write_paragraph() - - with formatter.indentation(): - formatter.write_text(text) - - def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes all the options into the formatter if they exist.""" - opts = [] - for param in self.get_params(ctx): - rv = param.get_help_record(ctx) - if rv is not None: - opts.append(rv) - - if opts: - with formatter.section(_("Options")): - formatter.write_dl(opts) - - def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the epilog into the formatter if it exists.""" - if self.epilog: - epilog = inspect.cleandoc(self.epilog) - formatter.write_paragraph() - - with formatter.indentation(): - formatter.write_text(epilog) - - def 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. - :param attrs: Other command arguments described in :class:`Command`. - """ - - 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) - return f(inner, *args, **kwargs) - - self._result_callback = rv = update_wrapper(t.cast(F, function), f) - return rv # type: ignore[return-value] - - return decorator - - def 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 ``commands`` 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.MutableMapping[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.MutableMapping[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 - - func: t.Optional[t.Callable[..., t.Any]] = None - - if args and callable(args[0]): - assert ( - len(args) == 1 and not kwargs - ), "Use 'command(**kwargs)(callable)' to provide arguments." - (func,) = args - args = () - - if self.command_class and kwargs.get("cls") is None: - kwargs["cls"] = self.command_class - - def decorator(f: t.Callable[..., t.Any]) -> Command: - cmd: Command = command(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - - if func is not None: - return decorator(func) - - return decorator - - @t.overload - def group(self, __func: t.Callable[..., t.Any]) -> "Group": ... - - @t.overload - def group( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: ... - - def group( - self, *args: t.Any, **kwargs: t.Any - ) -> t.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[..., t.Any]] = 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. - - See :class:`MultiCommand` and :class:`Command` for the description of - ``name`` and ``attrs``. - """ - - 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 latter is converted into the former - automatically if supported. - :param required: controls if this is optional or not. - :param default: the default value if omitted. This can also be a callable, - in which case it's invoked when the default is needed - without any arguments. - :param callback: A function to further process or validate the value - after type conversion. It is called as ``f(ctx, param, value)`` - and must return the value. It is called for all sources, - including prompts. - :param nargs: the number of arguments to match. If not ``1`` the return - value is a tuple instead of single value. The default for - nargs is ``1`` (except if the type is a tuple, then it's - the arity of the tuple). If ``nargs=-1``, all remaining - parameters are collected. - :param metavar: how the value is represented in the help page. - :param expose_value: if this is `True` then the value is passed onwards - to the command callback and stored on the context, - otherwise it's skipped. - :param is_eager: eager values are processed before non eager ones. This - should not be set for arguments or it will inverse the - order of processing. - :param envvar: 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: t.Optional[str] - self.opts: t.List[str] - self.secondary_opts: t.List[str] - self.name, self.opts, self.secondary_opts = self._parse_decls( - param_decls or (), expose_value - ) - self.type: types.ParamType = types.convert_type(type, default) - - # Default nargs to what the type tells us if we have that - # information available. - if nargs is None: - if self.type.is_composite: - nargs = self.type.arity - else: - nargs = 1 - - self.required = required - self.callback = callback - self.nargs = nargs - self.multiple = multiple - self.expose_value = expose_value - self.default = default - self.is_eager = is_eager - self.metavar = metavar - self.envvar = envvar - self._custom_shell_complete = shell_complete - - 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[t.Any]: - try: - return _check_iter(value) - except TypeError: - # This should only happen when passing in args manually, - # the parser should construct an iterable when parsing - # the command line. - raise BadParameter( - _("Value must be an iterable."), ctx=ctx, param=self - ) from None - - if self.nargs == 1 or self.type.is_composite: - - def convert(value: t.Any) -> t.Any: - return self.type(value, param=self, ctx=ctx) - - elif self.nargs == -1: - - def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] - return tuple(self.type(x, self, ctx) for x in check_iter(value)) - - else: # nargs > 1 - - def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] - value = tuple(check_iter(value)) - - if len(value) != self.nargs: - raise BadParameter( - ngettext( - "Takes {nargs} values but 1 was given.", - "Takes {nargs} values but {len} were given.", - len(value), - ).format(nargs=self.nargs, len=len(value)), - ctx=ctx, - param=self, - ) - - return tuple(self.type(x, self, ctx) for x in value) - - if self.multiple: - return tuple(convert(x) for x in check_iter(value)) - - return convert(value) - - def value_is_missing(self, value: t.Any) -> bool: - 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. - :param attrs: Other command arguments described in :class:`Parameter`. - - .. 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 - - self.default: t.Union[t.Any, t.Callable[[], t.Any]] - - if is_flag and default_is_missing and not self.required: - if multiple: - self.default = () - else: - self.default = False - - if flag_value is None: - flag_value = not self.default - - self.type: types.ParamType - 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: bool = 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'.") - - 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( - f"Could not determine name for option with declarations {decls!r}" - ) - - if not opts and not secondary_opts: - raise TypeError( - f"No options defined but a name was passed ({name})." - " Did you mean to declare an argument instead? Did" - f" you mean to pass '--{name}'?" - ) - - return name, opts, secondary_opts - - def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: - if self.multiple: - action = "append" - elif self.count: - action = "count" - else: - action = "store" - - if self.is_flag: - action = f"{action}_const" - - if self.is_bool_flag and self.secondary_opts: - parser.add_option( - obj=self, opts=self.opts, dest=self.name, action=action, const=True - ) - parser.add_option( - obj=self, - opts=self.secondary_opts, - dest=self.name, - action=action, - const=False, - ) - else: - parser.add_option( - obj=self, - opts=self.opts, - dest=self.name, - action=action, - const=self.flag_value, - ) - else: - parser.add_option( - obj=self, - opts=self.opts, - dest=self.name, - action=action, - nargs=self.nargs, - ) - - def get_help_record(self, ctx: Context) -> 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 default_value else self.secondary_opts)[0] - )[1] - elif self.is_bool_flag and not self.secondary_opts and not default_value: - default_string = "" - elif default_value == "": - default_string = '""' - else: - default_string = str(default_value) - - if default_string: - extra.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 t.cast(Option, param).flag_value - - 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 constructor of :class:`Parameter`. - """ - - 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("Argument is marked as exposed, but does not have a name.") - if len(decls) == 1: - name = arg = decls[0] - name = name.replace("-", "_").lower() - else: - raise TypeError( - "Arguments take exactly one parameter declaration, got" - f" {len(decls)}." - ) - 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/serverenv/lib/python3.9/site-packages/click/decorators.py b/serverenv/lib/python3.9/site-packages/click/decorators.py deleted file mode 100644 index bcf8906..0000000 --- a/serverenv/lib/python3.9/site-packages/click/decorators.py +++ /dev/null @@ -1,562 +0,0 @@ -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 - -if t.TYPE_CHECKING: - import typing_extensions as te - - P = te.ParamSpec("P") - -R = t.TypeVar("R") -T = t.TypeVar("T") -_AnyCallable = t.Callable[..., t.Any] -FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command]) - - -def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]": - """Marks a callback as wanting to receive the current context - object as first argument. - """ - - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": - return f(get_current_context(), *args, **kwargs) - - return update_wrapper(new_func, f) - - -def pass_obj(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": - """Similar to :func:`pass_context`, but only pass the object on the - context onwards (:attr:`Context.obj`). This is useful if that object - represents the state of a nested system. - """ - - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": - return f(get_current_context().obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - -def make_pass_decorator( - object_type: t.Type[T], ensure: bool = False -) -> t.Callable[["t.Callable[te.Concatenate[T, P], R]"], "t.Callable[P, R]"]: - """Given an object type this creates a decorator that will work - similar to :func:`pass_obj` but instead of passing the object of the - current context, it will find the innermost context of type - :func:`object_type`. - - This generates a decorator that works roughly like this:: - - from functools import update_wrapper - - def decorator(f): - @pass_context - def new_func(ctx, *args, **kwargs): - obj = ctx.find_object(object_type) - return ctx.invoke(f, obj, *args, **kwargs) - return update_wrapper(new_func, f) - return decorator - - :param object_type: the type of the object to pass. - :param ensure: if set to `True`, a new object will be created and - remembered on the context if it's not there yet. - """ - - def decorator(f: "t.Callable[te.Concatenate[T, P], R]") -> "t.Callable[P, R]": - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": - ctx = get_current_context() - - obj: t.Optional[T] - if ensure: - obj = ctx.ensure_object(object_type) - else: - obj = ctx.find_object(object_type) - - if obj is None: - raise RuntimeError( - "Managed to invoke callback without a context" - f" object of type {object_type.__name__!r}" - " existing." - ) - - return ctx.invoke(f, obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - return decorator - - -def pass_meta_key( - key: str, *, doc_description: t.Optional[str] = None -) -> "t.Callable[[t.Callable[te.Concatenate[t.Any, P], R]], t.Callable[P, R]]": - """Create a decorator that passes a key from - :attr:`click.Context.meta` as the first argument to the decorated - function. - - :param key: Key in ``Context.meta`` to pass. - :param doc_description: Description of the object being passed, - inserted into the decorator's docstring. Defaults to "the 'key' - key from Context.meta". - - .. versionadded:: 8.0 - """ - - def decorator(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R: - ctx = get_current_context() - obj = ctx.meta[key] - return ctx.invoke(f, obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - if doc_description is None: - doc_description = f"the {key!r} key from :attr:`click.Context.meta`" - - decorator.__doc__ = ( - f"Decorator that passes {doc_description} as the first argument" - " to the decorated function." - ) - return decorator - - -CmdType = t.TypeVar("CmdType", bound=Command) - - -# variant: no call, directly as decorator for a function. -@t.overload -def command(name: _AnyCallable) -> Command: ... - - -# variant: with positional name and with positional or keyword cls argument: -# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) -@t.overload -def command( - name: t.Optional[str], - cls: t.Type[CmdType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], CmdType]: ... - - -# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) -@t.overload -def command( - name: None = None, - *, - cls: t.Type[CmdType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], CmdType]: ... - - -# variant: with optional string name, no cls argument provided. -@t.overload -def command( - name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any -) -> t.Callable[[_AnyCallable], Command]: ... - - -def command( - name: t.Union[t.Optional[str], _AnyCallable] = None, - cls: t.Optional[t.Type[CmdType]] = None, - **attrs: t.Any, -) -> t.Union[Command, t.Callable[[_AnyCallable], t.Union[Command, CmdType]]]: - r"""Creates a new :class:`Command` and uses the decorated function as - callback. This will also automatically attach all decorated - :func:`option`\s and :func:`argument`\s as parameters to the command. - - The name of the command defaults to the name of the function 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[[_AnyCallable], 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 = t.cast(t.Type[CmdType], Command) - - def decorator(f: _AnyCallable) -> CmdType: - if isinstance(f, Command): - raise TypeError("Attempted to convert a callback into a command twice.") - - attr_params = attrs.pop("params", None) - params = attr_params if attr_params is not None else [] - - try: - decorator_params = f.__click_params__ # type: ignore - except AttributeError: - pass - else: - del f.__click_params__ # type: ignore - params.extend(reversed(decorator_params)) - - if attrs.get("help") is None: - attrs["help"] = f.__doc__ - - if t.TYPE_CHECKING: - assert cls is not None - assert not callable(name) - - cmd = cls( - name=name or f.__name__.lower().replace("_", "-"), - callback=f, - params=params, - **attrs, - ) - cmd.__doc__ = f.__doc__ - return cmd - - if func is not None: - return decorator(func) - - return decorator - - -GrpType = t.TypeVar("GrpType", bound=Group) - - -# variant: no call, directly as decorator for a function. -@t.overload -def group(name: _AnyCallable) -> Group: ... - - -# variant: with positional name and with positional or keyword cls argument: -# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) -@t.overload -def group( - name: t.Optional[str], - cls: t.Type[GrpType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], GrpType]: ... - - -# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) -@t.overload -def group( - name: None = None, - *, - cls: t.Type[GrpType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], GrpType]: ... - - -# variant: with optional string name, no cls argument provided. -@t.overload -def group( - name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any -) -> t.Callable[[_AnyCallable], Group]: ... - - -def group( - name: t.Union[str, _AnyCallable, None] = None, - cls: t.Optional[t.Type[GrpType]] = None, - **attrs: t.Any, -) -> t.Union[Group, t.Callable[[_AnyCallable], t.Union[Group, GrpType]]]: - """Creates a new :class:`Group` with a function as callback. This - works otherwise the same as :func:`command` just that the `cls` - parameter is set to :class:`Group`. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - """ - if cls is None: - cls = t.cast(t.Type[GrpType], Group) - - if callable(name): - return command(cls=cls, **attrs)(name) - - return command(name, cls, **attrs) - - -def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: - if isinstance(f, Command): - f.params.append(param) - else: - if not hasattr(f, "__click_params__"): - f.__click_params__ = [] # type: ignore - - f.__click_params__.append(param) # type: ignore - - -def argument( - *param_decls: str, cls: t.Optional[t.Type[Argument]] = None, **attrs: t.Any -) -> t.Callable[[FC], FC]: - """Attaches an argument to the command. All positional arguments are - passed as parameter declarations to :class:`Argument`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Argument` instance manually - and attaching it to the :attr:`Command.params` list. - - For the default argument class, refer to :class:`Argument` and - :class:`Parameter` for descriptions of parameters. - - :param cls: the argument class to instantiate. This defaults to - :class:`Argument`. - :param param_decls: Passed as positional arguments to the constructor of - ``cls``. - :param attrs: Passed as keyword arguments to the constructor of ``cls``. - """ - if cls is None: - cls = Argument - - def decorator(f: FC) -> FC: - _param_memo(f, cls(param_decls, **attrs)) - return f - - return decorator - - -def option( - *param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any -) -> t.Callable[[FC], FC]: - """Attaches an option to the command. All positional arguments are - passed as parameter declarations to :class:`Option`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Option` instance manually - and attaching it to the :attr:`Command.params` list. - - For the default option class, refer to :class:`Option` and - :class:`Parameter` for descriptions of parameters. - - :param cls: the option class to instantiate. This defaults to - :class:`Option`. - :param param_decls: Passed as positional arguments to the constructor of - ``cls``. - :param attrs: Passed as keyword arguments to the constructor of ``cls``. - """ - if cls is None: - cls = Option - - def decorator(f: FC) -> FC: - _param_memo(f, cls(param_decls, **attrs)) - return f - - return decorator - - -def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Add a ``--yes`` option which shows a prompt before continuing if - not passed. If the prompt is declined, the program will exit. - - :param param_decls: One or more option names. Defaults to the single - value ``"--yes"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - - def callback(ctx: Context, param: Parameter, value: bool) -> None: - if not value: - ctx.abort() - - if not param_decls: - param_decls = ("--yes",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("callback", callback) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("prompt", "Do you want to continue?") - kwargs.setdefault("help", "Confirm the action without prompting.") - return option(*param_decls, **kwargs) - - -def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Add a ``--password`` option which prompts for a password, hiding - input and asking to enter the value again for confirmation. - - :param param_decls: One or more option names. Defaults to the single - value ``"--password"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - if not param_decls: - param_decls = ("--password",) - - kwargs.setdefault("prompt", True) - kwargs.setdefault("confirmation_prompt", True) - kwargs.setdefault("hide_input", True) - return option(*param_decls, **kwargs) - - -def version_option( - version: 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 - 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( - 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) - - -class HelpOption(Option): - """Pre-configured ``--help`` option which immediately prints the help page - and exits the program. - """ - - def __init__( - self, - param_decls: t.Optional[t.Sequence[str]] = None, - **kwargs: t.Any, - ) -> None: - if not param_decls: - param_decls = ("--help",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("is_eager", True) - kwargs.setdefault("help", _("Show this message and exit.")) - kwargs.setdefault("callback", self.show_help) - - super().__init__(param_decls, **kwargs) - - @staticmethod - def show_help(ctx: Context, param: Parameter, value: bool) -> None: - """Callback that print the help page on ```` and exits.""" - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - -def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Decorator for the pre-configured ``--help`` option defined above. - - :param param_decls: One or more option names. Defaults to the single - value ``"--help"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - kwargs.setdefault("cls", HelpOption) - return option(*param_decls, **kwargs) diff --git a/serverenv/lib/python3.9/site-packages/click/exceptions.py b/serverenv/lib/python3.9/site-packages/click/exceptions.py deleted file mode 100644 index 0b83151..0000000 --- a/serverenv/lib/python3.9/site-packages/click/exceptions.py +++ /dev/null @@ -1,296 +0,0 @@ -import typing as t -from gettext import gettext as _ -from gettext import ngettext - -from ._compat import get_text_stderr -from .globals import resolve_color_default -from .utils import echo -from .utils import format_filename - -if t.TYPE_CHECKING: - from .core import Command - from .core import Context - from .core import Parameter - - -def _join_param_hints( - param_hint: 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) - # The context will be removed by the time we print the message, so cache - # the color settings here to be used later on (in `show`) - self.show_color: t.Optional[bool] = resolve_color_default() - self.message = message - - def format_message(self) -> str: - return self.message - - def __str__(self) -> str: - return self.message - - def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: - if file is None: - file = get_text_stderr() - - echo( - _("Error: {message}").format(message=self.format_message()), - file=file, - color=self.show_color, - ) - - -class UsageError(ClickException): - """An internal exception that signals a usage error. This typically - aborts any further handling. - - :param message: the error message to display. - :param ctx: optionally the context that caused this error. Click will - fill in the context automatically in some situations. - """ - - exit_code = 2 - - def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: - super().__init__(message) - self.ctx = ctx - self.cmd: t.Optional[Command] = self.ctx.command if self.ctx else None - - def show(self, file: t.Optional[t.IO[t.Any]] = 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: str = format_filename(filename) - self.filename = filename - - def format_message(self) -> str: - return _("Could not open file {filename!r}: {message}").format( - filename=self.ui_filename, message=self.message - ) - - -class Abort(RuntimeError): - """An internal signalling exception that signals Click to abort.""" - - -class Exit(RuntimeError): - """An exception that indicates that the application should exit with some - status code. - - :param code: the status code to exit with. - """ - - __slots__ = ("exit_code",) - - def __init__(self, code: int = 0) -> None: - self.exit_code: int = code diff --git a/serverenv/lib/python3.9/site-packages/click/formatting.py b/serverenv/lib/python3.9/site-packages/click/formatting.py deleted file mode 100644 index ddd2a2f..0000000 --- a/serverenv/lib/python3.9/site-packages/click/formatting.py +++ /dev/null @@ -1,301 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/click/globals.py b/serverenv/lib/python3.9/site-packages/click/globals.py deleted file mode 100644 index 191e712..0000000 --- a/serverenv/lib/python3.9/site-packages/click/globals.py +++ /dev/null @@ -1,67 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/click/parser.py b/serverenv/lib/python3.9/site-packages/click/parser.py deleted file mode 100644 index 600b843..0000000 --- a/serverenv/lib/python3.9/site-packages/click/parser.py +++ /dev/null @@ -1,531 +0,0 @@ -""" -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: t.Set[str] = set() - - for opt in opts: - prefix, value = split_opt(opt) - if not prefix: - raise ValueError(f"Invalid start character for option ({opt})") - self.prefixes.add(prefix[0]) - if len(prefix) == 1 and len(value) == 1: - self._short_opts.append(opt) - else: - self._long_opts.append(opt) - self.prefixes.add(prefix) - - if action is None: - action = "store" - - self.dest = dest - self.action = action - self.nargs = nargs - self.const = const - self.obj = obj - - @property - def takes_value(self) -> bool: - return self.action in ("store", "append") - - def process(self, value: t.Any, state: "ParsingState") -> None: - if self.action == "store": - state.opts[self.dest] = value # type: ignore - elif self.action == "store_const": - state.opts[self.dest] = self.const # type: ignore - elif self.action == "append": - state.opts.setdefault(self.dest, []).append(value) # type: ignore - elif self.action == "append_const": - state.opts.setdefault(self.dest, []).append(self.const) # type: ignore - elif self.action == "count": - state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore - else: - raise ValueError(f"unknown action '{self.action}'") - state.order.append(self.obj) - - -class Argument: - def __init__(self, obj: "CoreArgument", dest: 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: bool = True - #: This tells the parser how to deal with unknown options. By - #: default it will error out (which is sensible), but there is a - #: second mode where it will ignore it and continue processing - #: after shifting all the unknown options into the resulting args. - self.ignore_unknown_options: bool = False - - if ctx is not None: - self.allow_interspersed_args = ctx.allow_interspersed_args - self.ignore_unknown_options = ctx.ignore_unknown_options - - self._short_opt: 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 recombine the string of the - # remaining options and re-attach the prefix, then report that - # to the state as new larg. This way there is basic combinatorics - # that can be achieved while still ignoring unknown arguments. - if self.ignore_unknown_options and unknown_options: - state.largs.append(f"{prefix}{''.join(unknown_options)}") - - def _get_value_from_state( - self, option_name: str, option: Option, state: ParsingState - ) -> 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/serverenv/lib/python3.9/site-packages/click/py.typed b/serverenv/lib/python3.9/site-packages/click/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/click/shell_completion.py b/serverenv/lib/python3.9/site-packages/click/shell_completion.py deleted file mode 100644 index 07d0f09..0000000 --- a/serverenv/lib/python3.9/site-packages/click/shell_completion.py +++ /dev/null @@ -1,603 +0,0 @@ -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.MutableMapping[str, t.Any], - prog_name: str, - complete_var: str, - instruction: str, -) -> int: - """Perform shell completion for the given CLI program. - - :param cli: Command being called. - :param ctx_args: Extra arguments to pass to - ``cli.make_context``. - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. - :param instruction: Value of ``complete_var`` with the completion - instruction and shell, in the form ``instruction_shell``. - :return: Status code to exit with. - """ - shell, _, instruction = instruction.partition("_") - comp_cls = get_completion_class(shell) - - if comp_cls is None: - return 1 - - comp = comp_cls(cli, ctx_args, prog_name, complete_var) - - if instruction == "source": - echo(comp.source()) - return 0 - - if instruction == "complete": - echo(comp.complete()) - return 0 - - return 1 - - -class CompletionItem: - """Represents a completion value and metadata about the value. The - default metadata is ``type`` to indicate special shell handling, - and ``help`` if a shell supports showing a help string next to the - value. - - Arbitrary parameters can be passed when creating the object, and - accessed using ``item.attr``. If an attribute wasn't passed, - accessing it returns ``None``. - - :param value: The completion suggestion. - :param type: Tells the shell script to provide special completion - support for the type. Click uses ``"dir"`` and ``"file"``. - :param help: String shown next to the value if supported. - :param kwargs: Arbitrary metadata. The built-in implementations - don't use this, but custom type completions paired with custom - shell support could use it. - """ - - __slots__ = ("value", "type", "help", "_info") - - def __init__( - self, - value: t.Any, - type: str = "plain", - help: t.Optional[str] = None, - **kwargs: t.Any, - ) -> None: - self.value: t.Any = value - self.type: str = type - self.help: t.Optional[str] = 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 -} - -if [[ $zsh_eval_context[-1] == loadautofunc ]]; then - # autoload from fpath, call function directly - %(complete_func)s "$@" -else - # eval/source/. command, register function for later - compdef %(complete_func)s %(prog_name)s -fi -""" - -_SOURCE_FISH = """\ -function %(complete_func)s; - set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ -COMP_CWORD=(commandline -t) %(prog_name)s); - - for completion in $response; - set -l metadata (string split "," $completion); - - if test $metadata[1] = "dir"; - __fish_complete_directories $metadata[2]; - else if test $metadata[1] = "file"; - __fish_complete_path $metadata[2]; - else if test $metadata[1] = "plain"; - echo $metadata[2]; - end; - end; -end; - -complete --no-files --command %(prog_name)s --arguments \ -"(%(complete_func)s)"; -""" - - -class ShellComplete: - """Base class for providing shell completion support. A subclass for - a given shell will override attributes and methods to implement the - completion instructions (``source`` and ``complete``). - - :param cli: Command being called. - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. - - .. versionadded:: 8.0 - """ - - name: t.ClassVar[str] - """Name to register the shell as with :func:`add_completion_class`. - This is used in completion instructions (``{name}_source`` and - ``{name}_complete``). - """ - - source_template: t.ClassVar[str] - """Completion script template formatted by :meth:`source`. This must - be provided by subclasses. - """ - - def __init__( - self, - cli: BaseCommand, - ctx_args: t.MutableMapping[str, t.Any], - prog_name: str, - complete_var: str, - ) -> None: - self.cli = cli - self.ctx_args = ctx_args - self.prog_name = prog_name - self.complete_var = complete_var - - @property - def func_name(self) -> str: - """The name of the shell function defined by the completion - script. - """ - safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) - return f"_{safe_name}_completion" - - def source_vars(self) -> 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 - - @staticmethod - def _check_version() -> None: - import shutil - import subprocess - - bash_exe = shutil.which("bash") - - if bash_exe is None: - match = None - else: - output = subprocess.run( - [bash_exe, "--norc", "-c", 'echo "${BASH_VERSION}"'], - stdout=subprocess.PIPE, - ) - match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) - - if match is not None: - major, minor = match.groups() - - if major < "4" or major == "4" and minor < "4": - echo( - _( - "Shell completion is not supported for Bash" - " versions older than 4.4." - ), - err=True, - ) - else: - echo( - _("Couldn't detect Bash version, shell completion is not supported."), - err=True, - ) - - def source(self) -> str: - self._check_version() - return super().source() - - def get_completion_args(self) -> 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}" - - -ShellCompleteType = t.TypeVar("ShellCompleteType", bound=t.Type[ShellComplete]) - - -_available_shells: t.Dict[str, t.Type[ShellComplete]] = { - "bash": BashComplete, - "fish": FishComplete, - "zsh": ZshComplete, -} - - -def add_completion_class( - cls: ShellCompleteType, name: t.Optional[str] = None -) -> ShellCompleteType: - """Register a :class:`ShellComplete` subclass under the given name. - The name will be provided by the completion instruction environment - variable during completion. - - :param cls: The completion class that will handle completion for the - shell. - :param name: Name to register the class under. Defaults to the - class's ``name`` attribute. - """ - if name is None: - name = cls.name - - _available_shells[name] = cls - - return cls - - -def get_completion_class(shell: str) -> 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 - # Will be None if expose_value is False. - value = ctx.params.get(param.name) - return ( - param.nargs == -1 - or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE - or ( - param.nargs > 1 - and isinstance(value, (tuple, list)) - and len(value) < param.nargs - ) - ) - - -def _start_of_option(ctx: Context, value: str) -> bool: - """Check if the value looks like the start of an option.""" - if not value: - return False - - c = value[0] - return c in ctx._opt_prefixes - - -def _is_incomplete_option(ctx: Context, args: 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.MutableMapping[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: - sub_ctx = ctx - - 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/serverenv/lib/python3.9/site-packages/click/termui.py b/serverenv/lib/python3.9/site-packages/click/termui.py deleted file mode 100644 index c084f19..0000000 --- a/serverenv/lib/python3.9/site-packages/click/termui.py +++ /dev/null @@ -1,784 +0,0 @@ -import inspect -import io -import itertools -import sys -import typing as t -from gettext import gettext as _ - -from ._compat import isatty -from ._compat import strip_ansi -from .exceptions import Abort -from .exceptions import UsageError -from .globals import resolve_color_default -from .types import Choice -from .types import convert_type -from .types import ParamType -from .utils import echo -from .utils import LazyFile - -if t.TYPE_CHECKING: - from ._termui_impl import ProgressBar - -V = t.TypeVar("V") - -# The prompt functions to use. The doc tools currently override these -# functions to customize how they work. -visible_prompt_func: t.Callable[[str], str] = input - -_ansi_colors = { - "black": 30, - "red": 31, - "green": 32, - "yellow": 33, - "blue": 34, - "magenta": 35, - "cyan": 36, - "white": 37, - "reset": 39, - "bright_black": 90, - "bright_red": 91, - "bright_green": 92, - "bright_yellow": 93, - "bright_blue": 94, - "bright_magenta": 95, - "bright_cyan": 96, - "bright_white": 97, -} -_ansi_reset_all = "\033[0m" - - -def hidden_prompt_func(prompt: str) -> str: - import getpass - - return getpass.getpass(prompt) - - -def _build_prompt( - text: str, - suffix: str, - show_default: bool = False, - default: t.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 - - 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) - 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 - - # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor - echo("\033[2J\033[1;1H", nl=False) - - -def _interpret_color( - color: 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/serverenv/lib/python3.9/site-packages/click/testing.py b/serverenv/lib/python3.9/site-packages/click/testing.py deleted file mode 100644 index 772b215..0000000 --- a/serverenv/lib/python3.9/site-packages/click/testing.py +++ /dev/null @@ -1,483 +0,0 @@ -import contextlib -import io -import os -import shlex -import shutil -import sys -import tempfile -import typing as t -from types import TracebackType - -from . import _compat -from . import formatting -from . import termui -from . import utils -from ._compat import _find_binary_reader - -if t.TYPE_CHECKING: - from .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[t.Any]]], charset: str -) -> t.BinaryIO: - # Is already an input stream. - if hasattr(input, "read"): - rv = _find_binary_reader(t.cast(t.IO[t.Any], input)) - - if rv is not None: - return rv - - raise TypeError("Could not find binary reader for input stream.") - - if input is None: - input = b"" - elif isinstance(input, str): - input = input.encode(charset) - - return io.BytesIO(input) - - -class Result: - """Holds the captured result of an invoked CLI script.""" - - 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: t.Mapping[str, t.Optional[str]] = 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[t.Any]]] = 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[t.Any]] = 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 - old__compat_should_strip_ansi = _compat.should_strip_ansi - termui.visible_prompt_func = visible_input - termui.hidden_prompt_func = hidden_input - termui._getchar = _getchar - utils.should_strip_ansi = should_strip_ansi # type: ignore - _compat.should_strip_ansi = should_strip_ansi - - old_env = {} - try: - for key, value in env.items(): - old_env[key] = os.environ.get(key) - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - yield (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 - _compat.should_strip_ansi = old__compat_should_strip_ansi - 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[t.Any]]] = 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[str]"]] = 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) - os.chdir(dt) - - try: - yield dt - finally: - os.chdir(cwd) - - if temp_dir is None: - try: - shutil.rmtree(dt) - except OSError: - pass diff --git a/serverenv/lib/python3.9/site-packages/click/types.py b/serverenv/lib/python3.9/site-packages/click/types.py deleted file mode 100644 index a70fd58..0000000 --- a/serverenv/lib/python3.9/site-packages/click/types.py +++ /dev/null @@ -1,1093 +0,0 @@ -import os -import stat -import sys -import typing as t -from datetime import datetime -from gettext import gettext as _ -from gettext import ngettext - -from ._compat import _get_argv_encoding -from ._compat import open_stream -from .exceptions import BadParameter -from .utils import format_filename -from .utils import LazyFile -from .utils import safecall - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .core import Context - from .core import Parameter - from .shell_completion import CompletionItem - - -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: str = 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 = sys.getfilesystemencoding() - if fs_enc != enc: - try: - value = value.decode(fs_enc) - except UnicodeError: - value = value.decode("utf-8", "replace") - else: - value = value.decode("utf-8", "replace") - return value - return str(value) - - def __repr__(self) -> str: - return "STRING" - - -class Choice(ParamType): - """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: t.Sequence[str] = 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[t.Any]] - - 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. - - Files can also be opened atomically in which case all writes go into a - separate file in the same folder and upon completion the file will - be moved over to the original location. This is useful if a file - regularly read by other users is modified. - - See :ref:`file-args` for more information. - - .. versionchanged:: 2.0 - Added the ``atomic`` parameter. - """ - - name = "filename" - envvar_list_splitter: t.ClassVar[str] = os.path.pathsep - - def __init__( - self, - mode: str = "r", - encoding: 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.Union[str, os.PathLike[str]]") -> bool: - if self.lazy is not None: - return self.lazy - if os.fspath(value) == "-": - return False - elif "w" in self.mode: - return True - return False - - def convert( - self, - value: t.Union[str, "os.PathLike[str]", t.IO[t.Any]], - param: t.Optional["Parameter"], - ctx: t.Optional["Context"], - ) -> t.IO[t.Any]: - if _is_file_like(value): - return value - - value = t.cast("t.Union[str, os.PathLike[str]]", value) - - try: - lazy = self.resolve_lazy_flag(value) - - if lazy: - lf = LazyFile( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - - if ctx is not None: - ctx.call_on_close(lf.close_intelligently) - - return t.cast(t.IO[t.Any], lf) - - f, should_close = open_stream( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - - # If a context is provided, we automatically close the file - # at the end of the context execution (or flush out). If a - # context does not exist, it's the caller's responsibility to - # properly close the file. This for instance happens when the - # type is used with prompts. - if ctx is not None: - if should_close: - ctx.call_on_close(safecall(f.close)) - else: - ctx.call_on_close(safecall(f.flush)) - - return f - except OSError as e: - self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) - - def shell_complete( - self, ctx: "Context", param: "Parameter", incomplete: str - ) -> 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")] - - -def _is_file_like(value: t.Any) -> "te.TypeGuard[t.IO[t.Any]]": - return hasattr(value, "read") or hasattr(value, "write") - - -class Path(ParamType): - """The ``Path`` type is similar to the :class:`File` type, but - returns the filename instead of an open file. Various checks can be - enabled to validate the type of file and permissions. - - :param exists: The file or directory needs to exist for the value to - be valid. If this is not set to ``True``, and the file does not - exist, then all further checks are silently skipped. - :param file_okay: Allow a file as a value. - :param dir_okay: Allow a directory as a value. - :param readable: if true, a readable check is performed. - :param writable: if true, a writable check is performed. - :param executable: if true, an executable check is performed. - :param resolve_path: Make the value absolute and resolve any - symlinks. A ``~`` is not expanded, as this is supposed to be - done by the shell only. - :param allow_dash: Allow a single dash as a value, which indicates - a standard stream (but does not open it). Use - :func:`~click.open_file` to handle opening this value. - :param path_type: Convert the incoming path value to this type. If - ``None``, keep Python's default, which is ``str``. Useful to - convert to :class:`pathlib.Path`. - - .. versionchanged:: 8.1 - Added the ``executable`` parameter. - - .. versionchanged:: 8.0 - Allow passing ``path_type=pathlib.Path``. - - .. versionchanged:: 6.0 - Added the ``allow_dash`` parameter. - """ - - envvar_list_splitter: t.ClassVar[str] = os.path.pathsep - - def __init__( - self, - exists: bool = False, - file_okay: bool = True, - dir_okay: bool = True, - writable: bool = False, - readable: bool = True, - resolve_path: bool = False, - allow_dash: bool = False, - path_type: t.Optional[t.Type[t.Any]] = None, - executable: bool = False, - ): - self.exists = exists - self.file_okay = file_okay - self.dir_okay = dir_okay - self.readable = readable - self.writable = writable - self.executable = executable - self.resolve_path = resolve_path - self.allow_dash = allow_dash - self.type = path_type - - if self.file_okay and not self.dir_okay: - self.name: str = _("file") - elif self.dir_okay and not self.file_okay: - self.name = _("directory") - else: - self.name = _("path") - - def to_info_dict(self) -> 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, value: "t.Union[str, os.PathLike[str]]" - ) -> "t.Union[str, bytes, os.PathLike[str]]": - if self.type is not None and not isinstance(value, self.type): - if self.type is str: - return os.fsdecode(value) - elif self.type is bytes: - return os.fsencode(value) - else: - return t.cast("os.PathLike[str]", self.type(value)) - - return value - - def convert( - self, - value: "t.Union[str, os.PathLike[str]]", - param: t.Optional["Parameter"], - ctx: t.Optional["Context"], - ) -> "t.Union[str, bytes, os.PathLike[str]]": - rv = value - - is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") - - if not is_dash: - if self.resolve_path: - # 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=format_filename(value) - ), - param, - ctx, - ) - - if not self.file_okay and stat.S_ISREG(st.st_mode): - self.fail( - _("{name} {filename!r} is a file.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - if not self.dir_okay and stat.S_ISDIR(st.st_mode): - self.fail( - _("{name} {filename!r} is a directory.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.readable and not os.access(rv, os.R_OK): - self.fail( - _("{name} {filename!r} is not readable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.writable and not os.access(rv, os.W_OK): - self.fail( - _("{name} {filename!r} is not writable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.executable and not os.access(value, os.X_OK): - self.fail( - _("{name} {filename!r} is not executable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - return self.coerce_path_result(rv) - - def shell_complete( - self, ctx: "Context", param: "Parameter", incomplete: str - ) -> 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[t.Any], ParamType]]) -> None: - self.types: t.Sequence[ParamType] = [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/serverenv/lib/python3.9/site-packages/click/utils.py b/serverenv/lib/python3.9/site-packages/click/utils.py deleted file mode 100644 index 836c6f2..0000000 --- a/serverenv/lib/python3.9/site-packages/click/utils.py +++ /dev/null @@ -1,624 +0,0 @@ -import os -import re -import sys -import typing as t -from functools import update_wrapper -from types import ModuleType -from types import TracebackType - -from ._compat import _default_text_stderr -from ._compat import _default_text_stdout -from ._compat import _find_binary_writer -from ._compat import auto_wrap_for_ansi -from ._compat import binary_streams -from ._compat import open_stream -from ._compat import should_strip_ansi -from ._compat import strip_ansi -from ._compat import text_streams -from ._compat import WIN -from .globals import resolve_color_default - -if t.TYPE_CHECKING: - import typing_extensions as te - - P = te.ParamSpec("P") - -R = t.TypeVar("R") - - -def _posixify(name: str) -> str: - return "-".join(name.split()).lower() - - -def safecall(func: "t.Callable[P, R]") -> "t.Callable[P, t.Optional[R]]": - """Wraps a function so that it swallows exceptions.""" - - def wrapper(*args: "P.args", **kwargs: "P.kwargs") -> t.Optional[R]: - try: - return func(*args, **kwargs) - except Exception: - pass - return None - - return update_wrapper(wrapper, func) - - -def make_str(value: t.Any) -> str: - """Converts a value into a valid string.""" - if isinstance(value, bytes): - try: - return value.decode(sys.getfilesystemencoding()) - except UnicodeError: - return value.decode("utf-8", "replace") - return str(value) - - -def make_default_short_help(help: str, max_length: int = 45) -> str: - """Returns a condensed version of help string.""" - # Consider only the first paragraph. - paragraph_end = help.find("\n\n") - - if paragraph_end != -1: - help = help[:paragraph_end] - - # Collapse newlines, tabs, and spaces. - words = help.split() - - if not words: - return "" - - # The first paragraph started with a "no rewrap" marker, ignore it. - if words[0] == "\b": - words = words[1:] - - total_length = 0 - last_index = len(words) - 1 - - for i, word in enumerate(words): - total_length += len(word) + (i > 0) - - if total_length > max_length: # too long, truncate - break - - if word[-1] == ".": # sentence end, truncate without "..." - return " ".join(words[: i + 1]) - - if total_length == max_length and i != last_index: - break # not at sentence end, truncate with "..." - else: - return " ".join(words) # no truncation needed - - # Account for the length of the suffix. - total_length += len("...") - - # remove words until the length is short enough - while i > 0: - total_length -= len(words[i]) + (i > 0) - - if total_length <= max_length: - break - - i -= 1 - - return " ".join(words[:i]) + "..." - - -class LazyFile: - """A lazy file works like a regular file but it does not fully open - the file but it does perform some basic checks early to see if the - filename parameter does make sense. This is useful for safely opening - files for writing. - """ - - def __init__( - self, - filename: t.Union[str, "os.PathLike[str]"], - mode: str = "r", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", - atomic: bool = False, - ): - self.name: str = os.fspath(filename) - self.mode = mode - self.encoding = encoding - self.errors = errors - self.atomic = atomic - self._f: t.Optional[t.IO[t.Any]] - self.should_close: bool - - if self.name == "-": - self._f, self.should_close = open_stream(filename, mode, encoding, errors) - else: - if "r" in mode: - # Open and close the file in case we're opening it for - # reading so that we can catch at least some errors in - # some cases early. - open(filename, mode).close() - self._f = None - self.should_close = True - - def __getattr__(self, name: str) -> t.Any: - return getattr(self.open(), name) - - def __repr__(self) -> str: - if self._f is not None: - return repr(self._f) - return f"" - - def open(self) -> t.IO[t.Any]: - """Opens the file if it's not yet open. This call might fail with - a :exc:`FileError`. Not handling this error will produce an error - that Click shows. - """ - if self._f is not None: - return self._f - try: - rv, self.should_close = open_stream( - self.name, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - except OSError as e: - from .exceptions import FileError - - raise FileError(self.name, hint=e.strerror) from e - self._f = rv - return rv - - def close(self) -> None: - """Closes the underlying file, no matter what.""" - if self._f is not None: - self._f.close() - - def close_intelligently(self) -> None: - """This function only closes the file if it was opened by the lazy - file wrapper. For instance this will never close stdin. - """ - if self.should_close: - self.close() - - def __enter__(self) -> "LazyFile": - return self - - def __exit__( - self, - exc_type: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - 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[t.Any]) -> None: - self._file: t.IO[t.Any] = file - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._file, name) - - def __enter__(self) -> "KeepOpenFile": - return self - - def __exit__( - self, - exc_type: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - 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() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if file is None: - return - - # Convert non bytes/text into the native string type. - if message is not None and not isinstance(message, (str, bytes, bytearray)): - out: 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, color) # 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: t.Union[str, "os.PathLike[str]"], - mode: str = "r", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", - lazy: bool = False, - atomic: bool = False, -) -> t.IO[t.Any]: - """Open a file, with extra behavior to handle ``'-'`` to indicate - a standard stream, lazy open on write, and atomic write. Similar to - the behavior of the :class:`~click.File` param type. - - If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is - wrapped so that using it in a context manager will not close it. - This makes it possible to use the function without accidentally - closing a standard stream: - - .. code-block:: python - - with open_file(filename) as f: - ... - - :param filename: The name or Path of the file to open, or ``'-'`` for - ``stdin``/``stdout``. - :param mode: The mode in which to open the file. - :param encoding: The encoding to decode or encode a file opened in - text mode. - :param errors: The error handling mode. - :param lazy: Wait to open the file until it is accessed. For read - mode, the file is temporarily opened to raise access errors - early, then closed until it is read again. - :param atomic: Write to a temporary file and replace the given file - on close. - - .. versionadded:: 3.0 - """ - if lazy: - return t.cast( - t.IO[t.Any], LazyFile(filename, mode, encoding, errors, atomic=atomic) - ) - - f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) - - if not should_close: - f = t.cast(t.IO[t.Any], KeepOpenFile(f)) - - return f - - -def format_filename( - filename: "t.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]", - shorten: bool = False, -) -> str: - """Format a filename as a string for display. Ensures the filename can be - displayed by replacing any invalid bytes or surrogate escapes in the name - with the replacement character ``�``. - - Invalid bytes or surrogate escapes will raise an error when written to a - stream with ``errors="strict"``. This will typically happen with ``stdout`` - when the locale is something like ``en_GB.UTF-8``. - - Many scenarios *are* safe to write surrogates though, due to PEP 538 and - PEP 540, including: - - - Writing to ``stderr``, which uses ``errors="backslashreplace"``. - - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens - stdout and stderr with ``errors="surrogateescape"``. - - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. - - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. - Python opens stdout and stderr with ``errors="surrogateescape"``. - - :param filename: formats a filename for UI display. This will also convert - the filename into unicode without failing. - :param shorten: this optionally shortens the filename to strip of the - path that leads up to it. - """ - if shorten: - filename = os.path.basename(filename) - else: - filename = os.fspath(filename) - - if isinstance(filename, bytes): - filename = filename.decode(sys.getfilesystemencoding(), "replace") - else: - filename = filename.encode("utf-8", "surrogateescape").decode( - "utf-8", "replace" - ) - - return filename - - -def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: - r"""Returns the config folder for the application. The default behavior - is to return whatever is most appropriate for the operating system. - - To give you an idea, for an app called ``"Foo Bar"``, something like - the following folders could be returned: - - Mac OS X: - ``~/Library/Application Support/Foo Bar`` - Mac OS X (POSIX): - ``~/.foo-bar`` - Unix: - ``~/.config/foo-bar`` - Unix (POSIX): - ``~/.foo-bar`` - Windows (roaming): - ``C:\Users\\AppData\Roaming\Foo Bar`` - Windows (not roaming): - ``C:\Users\\AppData\Local\Foo Bar`` - - .. versionadded:: 2.0 - - :param app_name: the application name. This should be properly capitalized - and can contain whitespace. - :param roaming: controls if the folder should be roaming or not on Windows. - Has no effect otherwise. - :param force_posix: if this is set to `True` then on any POSIX system the - folder will be stored in the home folder with a leading - dot instead of the XDG config home or darwin's - application support folder. - """ - if WIN: - key = "APPDATA" if roaming else "LOCALAPPDATA" - folder = os.environ.get(key) - if folder is None: - folder = os.path.expanduser("~") - return os.path.join(folder, app_name) - if force_posix: - return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) - if sys.platform == "darwin": - return os.path.join( - os.path.expanduser("~/Library/Application Support"), app_name - ) - return os.path.join( - os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), - _posixify(app_name), - ) - - -class PacifyFlushWrapper: - """This wrapper is used to catch and suppress BrokenPipeErrors resulting - from ``.flush()`` being called on broken pipe during the shutdown/final-GC - of the Python interpreter. Notably ``.flush()`` is always called on - ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any - other cleanup code, and the case where the underlying file is not a broken - pipe, all calls and attributes are proxied. - """ - - def __init__(self, wrapped: t.IO[t.Any]) -> None: - self.wrapped = wrapped - - def flush(self) -> None: - try: - self.wrapped.flush() - except OSError as e: - import errno - - if e.errno != errno.EPIPE: - raise - - def __getattr__(self, attr: str) -> t.Any: - return getattr(self.wrapped, attr) - - -def _detect_program_name( - path: 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. - # It is set to "" inside a Shiv or PEX zipapp. - if getattr(_main, "__package__", None) in {None, ""} or ( - os.name == "nt" - and _main.__package__ == "" - and not os.path.exists(path) - and os.path.exists(f"{path}.exe") - ): - # Executed a file, like "python app.py". - return os.path.basename(path) - - # Executed a module, like "python -m example". - # Rewritten by Python from "-m script" to "/path/to/script.py". - # Need to look at main module to determine how it was executed. - py_module = t.cast(str, _main.__package__) - name = os.path.splitext(os.path.basename(path))[0] - - # A submodule like "example.cli". - if name != "__main__": - py_module = f"{py_module}.{name}" - - return f"python -m {py_module.lstrip('.')}" - - -def _expand_args( - args: 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/serverenv/lib/python3.9/site-packages/distutils-precedence.pth b/serverenv/lib/python3.9/site-packages/distutils-precedence.pth deleted file mode 100644 index 6de4198..0000000 --- a/serverenv/lib/python3.9/site-packages/distutils-precedence.pth +++ /dev/null @@ -1 +0,0 @@ -import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'stdlib') == 'local'; enabled and __import__('_distutils_hack').add_shim(); diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/METADATA deleted file mode 100644 index 45df9c8..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/METADATA +++ /dev/null @@ -1,159 +0,0 @@ -Metadata-Version: 2.4 -Name: exceptiongroup -Version: 1.3.0 -Summary: Backport of PEP 654 (exception groups) -Author-email: Alex Grönholm -Requires-Python: >=3.7 -Description-Content-Type: text/x-rst -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Typing :: Typed -License-File: LICENSE -Requires-Dist: typing-extensions >= 4.6.0; python_version < '3.13' -Requires-Dist: pytest >= 6 ; extra == "test" -Project-URL: Changelog, https://github.com/agronholm/exceptiongroup/blob/main/CHANGES.rst -Project-URL: Issue Tracker, https://github.com/agronholm/exceptiongroup/issues -Project-URL: Source code, https://github.com/agronholm/exceptiongroup -Provides-Extra: test - -.. image:: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml/badge.svg - :target: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml - :alt: Build Status -.. image:: https://coveralls.io/repos/github/agronholm/exceptiongroup/badge.svg?branch=main - :target: https://coveralls.io/github/agronholm/exceptiongroup?branch=main - :alt: Code Coverage - -This is a backport of the ``BaseExceptionGroup`` and ``ExceptionGroup`` classes from -Python 3.11. - -It contains the following: - -* The ``exceptiongroup.BaseExceptionGroup`` and ``exceptiongroup.ExceptionGroup`` - classes -* A utility function (``exceptiongroup.catch()``) for catching exceptions possibly - nested in an exception group -* Patches to the ``TracebackException`` class that properly formats exception groups - (installed on import) -* An exception hook that handles formatting of exception groups through - ``TracebackException`` (installed on import) -* Special versions of some of the functions from the ``traceback`` module, modified to - correctly handle exception groups even when monkey patching is disabled, or blocked by - another custom exception hook: - - * ``traceback.format_exception()`` - * ``traceback.format_exception_only()`` - * ``traceback.print_exception()`` - * ``traceback.print_exc()`` -* A backported version of ``contextlib.suppress()`` from Python 3.12.1 which also - handles suppressing exceptions inside exception groups - -If this package is imported on Python 3.11 or later, the built-in implementations of the -exception group classes are used instead, ``TracebackException`` is not monkey patched -and the exception hook won't be installed. - -See the `standard library documentation`_ for more information on exception groups. - -.. _standard library documentation: https://docs.python.org/3/library/exceptions.html - -Catching exceptions -=================== - -Due to the lack of the ``except*`` syntax introduced by `PEP 654`_ in earlier Python -versions, you need to use ``exceptiongroup.catch()`` to catch exceptions that are -potentially nested inside an exception group. This function returns a context manager -that calls the given handler for any exceptions matching the sole argument. - -The argument to ``catch()`` must be a dict (or any ``Mapping``) where each key is either -an exception class or an iterable of exception classes. Each value must be a callable -that takes a single positional argument. The handler will be called at most once, with -an exception group as an argument which will contain all the exceptions that are any -of the given types, or their subclasses. The exception group may contain nested groups -containing more matching exceptions. - -Thus, the following Python 3.11+ code: - -.. code-block:: python - - try: - ... - except* (ValueError, KeyError) as excgroup: - for exc in excgroup.exceptions: - print('Caught exception:', type(exc)) - except* RuntimeError: - print('Caught runtime error') - -would be written with this backport like this: - -.. code-block:: python - - from exceptiongroup import BaseExceptionGroup, catch - - def value_key_err_handler(excgroup: BaseExceptionGroup) -> None: - for exc in excgroup.exceptions: - print('Caught exception:', type(exc)) - - def runtime_err_handler(exc: BaseExceptionGroup) -> None: - print('Caught runtime error') - - with catch({ - (ValueError, KeyError): value_key_err_handler, - RuntimeError: runtime_err_handler - }): - ... - -**NOTE**: Just like with ``except*``, you cannot handle ``BaseExceptionGroup`` or -``ExceptionGroup`` with ``catch()``. - -Suppressing exceptions -====================== - -This library contains a backport of the ``contextlib.suppress()`` context manager from -Python 3.12.1. It allows you to selectively ignore certain exceptions, even when they're -inside exception groups: - -.. code-block:: python - - from exceptiongroup import suppress - - with suppress(RuntimeError): - raise ExceptionGroup("", [RuntimeError("boo")]) - -Notes on monkey patching -======================== - -To make exception groups render properly when an unhandled exception group is being -printed out, this package does two things when it is imported on any Python version -earlier than 3.11: - -#. The ``traceback.TracebackException`` class is monkey patched to store extra - information about exception groups (in ``__init__()``) and properly format them (in - ``format()``) -#. An exception hook is installed at ``sys.excepthook``, provided that no other hook is - already present. This hook causes the exception to be formatted using - ``traceback.TracebackException`` rather than the built-in rendered. - -If ``sys.exceptionhook`` is found to be set to something else than the default when -``exceptiongroup`` is imported, no monkeypatching is done at all. - -To prevent the exception hook and patches from being installed, set the environment -variable ``EXCEPTIONGROUP_NO_PATCH`` to ``1``. - -Formatting exception groups ---------------------------- - -Normally, the monkey patching applied by this library on import will cause exception -groups to be printed properly in tracebacks. But in cases when the monkey patching is -blocked by a third party exception hook, or monkey patching is explicitly disabled, -you can still manually format exceptions using the special versions of the ``traceback`` -functions, like ``format_exception()``, listed at the top of this page. They work just -like their counterparts in the ``traceback`` module, except that they use a separately -patched subclass of ``TracebackException`` to perform the rendering. - -Particularly in cases where a library installs its own exception hook, it is recommended -to use these special versions to do the actual formatting of exceptions/tracebacks. - -.. _PEP 654: https://www.python.org/dev/peps/pep-0654/ - diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/RECORD deleted file mode 100644 index 4dd41de..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/RECORD +++ /dev/null @@ -1,18 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/exceptiongroup/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/exceptiongroup/_catch.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/exceptiongroup/_exceptions.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/exceptiongroup/_formatting.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/exceptiongroup/_suppress.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/exceptiongroup/_version.cpython-39.pyc,, -exceptiongroup-1.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -exceptiongroup-1.3.0.dist-info/METADATA,sha256=oiAq-llXqOaV0B3dJN316SjtCpthQvuQjmVuVObbaeQ,6725 -exceptiongroup-1.3.0.dist-info/RECORD,, -exceptiongroup-1.3.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 -exceptiongroup-1.3.0.dist-info/licenses/LICENSE,sha256=blBw12UDHgrUA6HL-Qrm0ZoCKPgC4yC3rP9GCqcu1Hw,3704 -exceptiongroup/__init__.py,sha256=7DHS0hDk-RIs3IQc3SbZVB0-1MhiSCJ9XgvEyEloL7M,1049 -exceptiongroup/_catch.py,sha256=CaJez3E-Jkr-7B7RT3fzusdLWnuyeekooSFn7KyWt9s,4680 -exceptiongroup/_exceptions.py,sha256=wPwPsZ64SXEptuwb4XrTIa1Mc78uqF5vmCrXTdllLn4,11463 -exceptiongroup/_formatting.py,sha256=4UC6bUN3K-FxEX96_ozzgeX05fCyprl6qCVR-efBmQ0,21032 -exceptiongroup/_suppress.py,sha256=LX11PRNpchwfNWwEMY92nYN1F_5qFenQcS8EjIONXKE,1772 -exceptiongroup/_version.py,sha256=qDtcPZdKzxLpd8vVl6fpIFIMkWt2HK_cO9gLDwaHEdk,511 -exceptiongroup/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/WHEEL deleted file mode 100644 index d8b9936..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.12.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/licenses/LICENSE b/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/licenses/LICENSE deleted file mode 100644 index 50d4fa5..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup-1.3.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,73 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2022 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. - - -This project contains code copied from the Python standard library. -The following is the required license notice for those parts. - -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, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 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. diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup/__init__.py b/serverenv/lib/python3.9/site-packages/exceptiongroup/__init__.py deleted file mode 100644 index d8e36b2..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -__all__ = [ - "BaseExceptionGroup", - "ExceptionGroup", - "catch", - "format_exception", - "format_exception_only", - "print_exception", - "print_exc", - "suppress", -] - -import os -import sys - -from ._catch import catch -from ._version import version as __version__ # noqa: F401 - -if sys.version_info < (3, 11): - from ._exceptions import BaseExceptionGroup, ExceptionGroup - from ._formatting import ( - format_exception, - format_exception_only, - print_exc, - print_exception, - ) - - if os.getenv("EXCEPTIONGROUP_NO_PATCH") != "1": - from . import _formatting # noqa: F401 - - BaseExceptionGroup.__module__ = __name__ - ExceptionGroup.__module__ = __name__ -else: - from traceback import ( - format_exception, - format_exception_only, - print_exc, - print_exception, - ) - - BaseExceptionGroup = BaseExceptionGroup - ExceptionGroup = ExceptionGroup - -if sys.version_info < (3, 12, 1): - from ._suppress import suppress -else: - from contextlib import suppress diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup/_catch.py b/serverenv/lib/python3.9/site-packages/exceptiongroup/_catch.py deleted file mode 100644 index 0246568..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup/_catch.py +++ /dev/null @@ -1,138 +0,0 @@ -from __future__ import annotations - -import inspect -import sys -from collections.abc import Callable, Iterable, Mapping -from contextlib import AbstractContextManager -from types import TracebackType -from typing import TYPE_CHECKING, Any - -if sys.version_info < (3, 11): - from ._exceptions import BaseExceptionGroup - -if TYPE_CHECKING: - _Handler = Callable[[BaseExceptionGroup[Any]], Any] - - -class _Catcher: - def __init__(self, handler_map: Mapping[tuple[type[BaseException], ...], _Handler]): - self._handler_map = handler_map - - def __enter__(self) -> None: - pass - - def __exit__( - self, - etype: type[BaseException] | None, - exc: BaseException | None, - tb: TracebackType | None, - ) -> bool: - if exc is not None: - unhandled = self.handle_exception(exc) - if unhandled is exc: - return False - elif unhandled is None: - return True - else: - if isinstance(exc, BaseExceptionGroup): - try: - raise unhandled from exc.__cause__ - except BaseExceptionGroup: - # Change __context__ to __cause__ because Python 3.11 does this - # too - unhandled.__context__ = exc.__cause__ - raise - - raise unhandled from exc - - return False - - def handle_exception(self, exc: BaseException) -> BaseException | None: - excgroup: BaseExceptionGroup | None - if isinstance(exc, BaseExceptionGroup): - excgroup = exc - else: - excgroup = BaseExceptionGroup("", [exc]) - - new_exceptions: list[BaseException] = [] - for exc_types, handler in self._handler_map.items(): - matched, excgroup = excgroup.split(exc_types) - if matched: - try: - try: - raise matched - except BaseExceptionGroup: - result = handler(matched) - except BaseExceptionGroup as new_exc: - if new_exc is matched: - new_exceptions.append(new_exc) - else: - new_exceptions.extend(new_exc.exceptions) - except BaseException as new_exc: - new_exceptions.append(new_exc) - else: - if inspect.iscoroutine(result): - raise TypeError( - f"Error trying to handle {matched!r} with {handler!r}. " - "Exception handler must be a sync function." - ) from exc - - if not excgroup: - break - - if new_exceptions: - if len(new_exceptions) == 1: - return new_exceptions[0] - - return BaseExceptionGroup("", new_exceptions) - elif ( - excgroup and len(excgroup.exceptions) == 1 and excgroup.exceptions[0] is exc - ): - return exc - else: - return excgroup - - -def catch( - __handlers: Mapping[type[BaseException] | Iterable[type[BaseException]], _Handler], -) -> AbstractContextManager[None]: - if not isinstance(__handlers, Mapping): - raise TypeError("the argument must be a mapping") - - handler_map: dict[ - tuple[type[BaseException], ...], Callable[[BaseExceptionGroup]] - ] = {} - for type_or_iterable, handler in __handlers.items(): - iterable: tuple[type[BaseException]] - if isinstance(type_or_iterable, type) and issubclass( - type_or_iterable, BaseException - ): - iterable = (type_or_iterable,) - elif isinstance(type_or_iterable, Iterable): - iterable = tuple(type_or_iterable) - else: - raise TypeError( - "each key must be either an exception classes or an iterable thereof" - ) - - if not callable(handler): - raise TypeError("handlers must be callable") - - for exc_type in iterable: - if not isinstance(exc_type, type) or not issubclass( - exc_type, BaseException - ): - raise TypeError( - "each key must be either an exception classes or an iterable " - "thereof" - ) - - if issubclass(exc_type, BaseExceptionGroup): - raise TypeError( - "catching ExceptionGroup with catch() is not allowed. " - "Use except instead." - ) - - handler_map[iterable] = handler - - return _Catcher(handler_map) diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup/_exceptions.py b/serverenv/lib/python3.9/site-packages/exceptiongroup/_exceptions.py deleted file mode 100644 index f42c1ad..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup/_exceptions.py +++ /dev/null @@ -1,336 +0,0 @@ -from __future__ import annotations - -import sys -from collections.abc import Callable, Sequence -from functools import partial -from inspect import getmro, isclass -from typing import TYPE_CHECKING, Generic, Type, TypeVar, cast, overload - -if sys.version_info < (3, 13): - from typing_extensions import TypeVar - -_BaseExceptionT_co = TypeVar( - "_BaseExceptionT_co", bound=BaseException, covariant=True, default=BaseException -) -_BaseExceptionT = TypeVar("_BaseExceptionT", bound=BaseException) -_ExceptionT_co = TypeVar( - "_ExceptionT_co", bound=Exception, covariant=True, default=Exception -) -_ExceptionT = TypeVar("_ExceptionT", bound=Exception) -# using typing.Self would require a typing_extensions dependency on py<3.11 -_ExceptionGroupSelf = TypeVar("_ExceptionGroupSelf", bound="ExceptionGroup") -_BaseExceptionGroupSelf = TypeVar("_BaseExceptionGroupSelf", bound="BaseExceptionGroup") - - -def check_direct_subclass( - exc: BaseException, parents: tuple[type[BaseException]] -) -> bool: - for cls in getmro(exc.__class__)[:-1]: - if cls in parents: - return True - - return False - - -def get_condition_filter( - condition: type[_BaseExceptionT] - | tuple[type[_BaseExceptionT], ...] - | Callable[[_BaseExceptionT_co], bool], -) -> Callable[[_BaseExceptionT_co], bool]: - if isclass(condition) and issubclass( - cast(Type[BaseException], condition), BaseException - ): - return partial(check_direct_subclass, parents=(condition,)) - elif isinstance(condition, tuple): - if all(isclass(x) and issubclass(x, BaseException) for x in condition): - return partial(check_direct_subclass, parents=condition) - elif callable(condition): - return cast("Callable[[BaseException], bool]", condition) - - raise TypeError("expected a function, exception type or tuple of exception types") - - -def _derive_and_copy_attributes(self, excs): - eg = self.derive(excs) - eg.__cause__ = self.__cause__ - eg.__context__ = self.__context__ - eg.__traceback__ = self.__traceback__ - if hasattr(self, "__notes__"): - # Create a new list so that add_note() only affects one exceptiongroup - eg.__notes__ = list(self.__notes__) - return eg - - -class BaseExceptionGroup(BaseException, Generic[_BaseExceptionT_co]): - """A combination of multiple unrelated exceptions.""" - - def __new__( - cls: type[_BaseExceptionGroupSelf], - __message: str, - __exceptions: Sequence[_BaseExceptionT_co], - ) -> _BaseExceptionGroupSelf: - if not isinstance(__message, str): - raise TypeError(f"argument 1 must be str, not {type(__message)}") - if not isinstance(__exceptions, Sequence): - raise TypeError("second argument (exceptions) must be a sequence") - if not __exceptions: - raise ValueError( - "second argument (exceptions) must be a non-empty sequence" - ) - - for i, exc in enumerate(__exceptions): - if not isinstance(exc, BaseException): - raise ValueError( - f"Item {i} of second argument (exceptions) is not an exception" - ) - - if cls is BaseExceptionGroup: - if all(isinstance(exc, Exception) for exc in __exceptions): - cls = ExceptionGroup - - if issubclass(cls, Exception): - for exc in __exceptions: - if not isinstance(exc, Exception): - if cls is ExceptionGroup: - raise TypeError( - "Cannot nest BaseExceptions in an ExceptionGroup" - ) - else: - raise TypeError( - f"Cannot nest BaseExceptions in {cls.__name__!r}" - ) - - instance = super().__new__(cls, __message, __exceptions) - instance._exceptions = tuple(__exceptions) - return instance - - def __init__( - self, - __message: str, - __exceptions: Sequence[_BaseExceptionT_co], - *args: object, - ) -> None: - BaseException.__init__(self, __message, __exceptions, *args) - - def add_note(self, note: str) -> None: - if not isinstance(note, str): - raise TypeError( - f"Expected a string, got note={note!r} (type {type(note).__name__})" - ) - - if not hasattr(self, "__notes__"): - self.__notes__: list[str] = [] - - self.__notes__.append(note) - - @property - def message(self) -> str: - return self.args[0] - - @property - def exceptions( - self, - ) -> tuple[_BaseExceptionT_co | BaseExceptionGroup[_BaseExceptionT_co], ...]: - return tuple(self._exceptions) - - @overload - def subgroup( - self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] - ) -> ExceptionGroup[_ExceptionT] | None: ... - - @overload - def subgroup( - self, __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...] - ) -> BaseExceptionGroup[_BaseExceptionT] | None: ... - - @overload - def subgroup( - self, - __condition: Callable[[_BaseExceptionT_co | _BaseExceptionGroupSelf], bool], - ) -> BaseExceptionGroup[_BaseExceptionT_co] | None: ... - - def subgroup( - self, - __condition: type[_BaseExceptionT] - | tuple[type[_BaseExceptionT], ...] - | Callable[[_BaseExceptionT_co | _BaseExceptionGroupSelf], bool], - ) -> BaseExceptionGroup[_BaseExceptionT] | None: - condition = get_condition_filter(__condition) - modified = False - if condition(self): - return self - - exceptions: list[BaseException] = [] - for exc in self.exceptions: - if isinstance(exc, BaseExceptionGroup): - subgroup = exc.subgroup(__condition) - if subgroup is not None: - exceptions.append(subgroup) - - if subgroup is not exc: - modified = True - elif condition(exc): - exceptions.append(exc) - else: - modified = True - - if not modified: - return self - elif exceptions: - group = _derive_and_copy_attributes(self, exceptions) - return group - else: - return None - - @overload - def split( - self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] - ) -> tuple[ - ExceptionGroup[_ExceptionT] | None, - BaseExceptionGroup[_BaseExceptionT_co] | None, - ]: ... - - @overload - def split( - self, __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...] - ) -> tuple[ - BaseExceptionGroup[_BaseExceptionT] | None, - BaseExceptionGroup[_BaseExceptionT_co] | None, - ]: ... - - @overload - def split( - self, - __condition: Callable[[_BaseExceptionT_co | _BaseExceptionGroupSelf], bool], - ) -> tuple[ - BaseExceptionGroup[_BaseExceptionT_co] | None, - BaseExceptionGroup[_BaseExceptionT_co] | None, - ]: ... - - def split( - self, - __condition: type[_BaseExceptionT] - | tuple[type[_BaseExceptionT], ...] - | Callable[[_BaseExceptionT_co], bool], - ) -> ( - tuple[ - ExceptionGroup[_ExceptionT] | None, - BaseExceptionGroup[_BaseExceptionT_co] | None, - ] - | tuple[ - BaseExceptionGroup[_BaseExceptionT] | None, - BaseExceptionGroup[_BaseExceptionT_co] | None, - ] - | tuple[ - BaseExceptionGroup[_BaseExceptionT_co] | None, - BaseExceptionGroup[_BaseExceptionT_co] | None, - ] - ): - condition = get_condition_filter(__condition) - if condition(self): - return self, None - - matching_exceptions: list[BaseException] = [] - nonmatching_exceptions: list[BaseException] = [] - for exc in self.exceptions: - if isinstance(exc, BaseExceptionGroup): - matching, nonmatching = exc.split(condition) - if matching is not None: - matching_exceptions.append(matching) - - if nonmatching is not None: - nonmatching_exceptions.append(nonmatching) - elif condition(exc): - matching_exceptions.append(exc) - else: - nonmatching_exceptions.append(exc) - - matching_group: _BaseExceptionGroupSelf | None = None - if matching_exceptions: - matching_group = _derive_and_copy_attributes(self, matching_exceptions) - - nonmatching_group: _BaseExceptionGroupSelf | None = None - if nonmatching_exceptions: - nonmatching_group = _derive_and_copy_attributes( - self, nonmatching_exceptions - ) - - return matching_group, nonmatching_group - - @overload - def derive(self, __excs: Sequence[_ExceptionT]) -> ExceptionGroup[_ExceptionT]: ... - - @overload - def derive( - self, __excs: Sequence[_BaseExceptionT] - ) -> BaseExceptionGroup[_BaseExceptionT]: ... - - def derive( - self, __excs: Sequence[_BaseExceptionT] - ) -> BaseExceptionGroup[_BaseExceptionT]: - return BaseExceptionGroup(self.message, __excs) - - def __str__(self) -> str: - suffix = "" if len(self._exceptions) == 1 else "s" - return f"{self.message} ({len(self._exceptions)} sub-exception{suffix})" - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.args[0]!r}, {self.args[1]!r})" - - -class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception): - def __new__( - cls: type[_ExceptionGroupSelf], - __message: str, - __exceptions: Sequence[_ExceptionT_co], - ) -> _ExceptionGroupSelf: - return super().__new__(cls, __message, __exceptions) - - if TYPE_CHECKING: - - @property - def exceptions( - self, - ) -> tuple[_ExceptionT_co | ExceptionGroup[_ExceptionT_co], ...]: ... - - @overload # type: ignore[override] - def subgroup( - self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] - ) -> ExceptionGroup[_ExceptionT] | None: ... - - @overload - def subgroup( - self, __condition: Callable[[_ExceptionT_co | _ExceptionGroupSelf], bool] - ) -> ExceptionGroup[_ExceptionT_co] | None: ... - - def subgroup( - self, - __condition: type[_ExceptionT] - | tuple[type[_ExceptionT], ...] - | Callable[[_ExceptionT_co], bool], - ) -> ExceptionGroup[_ExceptionT] | None: - return super().subgroup(__condition) - - @overload - def split( - self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] - ) -> tuple[ - ExceptionGroup[_ExceptionT] | None, ExceptionGroup[_ExceptionT_co] | None - ]: ... - - @overload - def split( - self, __condition: Callable[[_ExceptionT_co | _ExceptionGroupSelf], bool] - ) -> tuple[ - ExceptionGroup[_ExceptionT_co] | None, ExceptionGroup[_ExceptionT_co] | None - ]: ... - - def split( - self: _ExceptionGroupSelf, - __condition: type[_ExceptionT] - | tuple[type[_ExceptionT], ...] - | Callable[[_ExceptionT_co], bool], - ) -> tuple[ - ExceptionGroup[_ExceptionT_co] | None, ExceptionGroup[_ExceptionT_co] | None - ]: - return super().split(__condition) diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup/_formatting.py b/serverenv/lib/python3.9/site-packages/exceptiongroup/_formatting.py deleted file mode 100644 index c383c50..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup/_formatting.py +++ /dev/null @@ -1,601 +0,0 @@ -# traceback_exception_init() adapted from trio -# -# _ExceptionPrintContext and traceback_exception_format() copied from the standard -# library -from __future__ import annotations - -import collections.abc -import sys -import textwrap -import traceback -from functools import singledispatch -from types import TracebackType -from typing import Any, List, Optional - -from ._exceptions import BaseExceptionGroup - -max_group_width = 15 -max_group_depth = 10 -_cause_message = ( - "\nThe above exception was the direct cause of the following exception:\n\n" -) - -_context_message = ( - "\nDuring handling of the above exception, another exception occurred:\n\n" -) - - -def _format_final_exc_line(etype, value): - valuestr = _safe_string(value, "exception") - if value is None or not valuestr: - line = f"{etype}\n" - else: - line = f"{etype}: {valuestr}\n" - - return line - - -def _safe_string(value, what, func=str): - try: - return func(value) - except BaseException: - return f"<{what} {func.__name__}() failed>" - - -class _ExceptionPrintContext: - def __init__(self): - self.seen = set() - self.exception_group_depth = 0 - self.need_close = False - - def indent(self): - return " " * (2 * self.exception_group_depth) - - def emit(self, text_gen, margin_char=None): - if margin_char is None: - margin_char = "|" - indent_str = self.indent() - if self.exception_group_depth: - indent_str += margin_char + " " - - if isinstance(text_gen, str): - yield textwrap.indent(text_gen, indent_str, lambda line: True) - else: - for text in text_gen: - yield textwrap.indent(text, indent_str, lambda line: True) - - -def exceptiongroup_excepthook( - etype: type[BaseException], value: BaseException, tb: TracebackType | None -) -> None: - sys.stderr.write("".join(traceback.format_exception(etype, value, tb))) - - -class PatchedTracebackException(traceback.TracebackException): - def __init__( - self, - exc_type: type[BaseException], - exc_value: BaseException, - exc_traceback: TracebackType | None, - *, - limit: int | None = None, - lookup_lines: bool = True, - capture_locals: bool = False, - compact: bool = False, - _seen: set[int] | None = None, - ) -> None: - kwargs: dict[str, Any] = {} - if sys.version_info >= (3, 10): - kwargs["compact"] = compact - - is_recursive_call = _seen is not None - if _seen is None: - _seen = set() - _seen.add(id(exc_value)) - - self.stack = traceback.StackSummary.extract( - traceback.walk_tb(exc_traceback), - limit=limit, - lookup_lines=lookup_lines, - capture_locals=capture_locals, - ) - self.exc_type = exc_type - # Capture now to permit freeing resources: only complication is in the - # unofficial API _format_final_exc_line - self._str = _safe_string(exc_value, "exception") - try: - self.__notes__ = getattr(exc_value, "__notes__", None) - except KeyError: - # Workaround for https://github.com/python/cpython/issues/98778 on Python - # <= 3.9, and some 3.10 and 3.11 patch versions. - HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ()) - if sys.version_info[:2] <= (3, 11) and isinstance(exc_value, HTTPError): - self.__notes__ = None - else: - raise - - if exc_type and issubclass(exc_type, SyntaxError): - # Handle SyntaxError's specially - self.filename = exc_value.filename - lno = exc_value.lineno - self.lineno = str(lno) if lno is not None else None - self.text = exc_value.text - self.offset = exc_value.offset - self.msg = exc_value.msg - if sys.version_info >= (3, 10): - end_lno = exc_value.end_lineno - self.end_lineno = str(end_lno) if end_lno is not None else None - self.end_offset = exc_value.end_offset - elif ( - exc_type - and issubclass(exc_type, (NameError, AttributeError)) - and getattr(exc_value, "name", None) is not None - ): - suggestion = _compute_suggestion_error(exc_value, exc_traceback) - if suggestion: - self._str += f". Did you mean: '{suggestion}'?" - - if lookup_lines: - # Force all lines in the stack to be loaded - for frame in self.stack: - frame.line - - self.__suppress_context__ = ( - exc_value.__suppress_context__ if exc_value is not None else False - ) - - # Convert __cause__ and __context__ to `TracebackExceptions`s, use a - # queue to avoid recursion (only the top-level call gets _seen == None) - if not is_recursive_call: - queue = [(self, exc_value)] - while queue: - te, e = queue.pop() - - if e and e.__cause__ is not None and id(e.__cause__) not in _seen: - cause = PatchedTracebackException( - type(e.__cause__), - e.__cause__, - e.__cause__.__traceback__, - limit=limit, - lookup_lines=lookup_lines, - capture_locals=capture_locals, - _seen=_seen, - ) - else: - cause = None - - if compact: - need_context = ( - cause is None and e is not None and not e.__suppress_context__ - ) - else: - need_context = True - if ( - e - and e.__context__ is not None - and need_context - and id(e.__context__) not in _seen - ): - context = PatchedTracebackException( - type(e.__context__), - e.__context__, - e.__context__.__traceback__, - limit=limit, - lookup_lines=lookup_lines, - capture_locals=capture_locals, - _seen=_seen, - ) - else: - context = None - - # Capture each of the exceptions in the ExceptionGroup along with each - # of their causes and contexts - if e and isinstance(e, BaseExceptionGroup): - exceptions = [] - for exc in e.exceptions: - texc = PatchedTracebackException( - type(exc), - exc, - exc.__traceback__, - lookup_lines=lookup_lines, - capture_locals=capture_locals, - _seen=_seen, - ) - exceptions.append(texc) - else: - exceptions = None - - te.__cause__ = cause - te.__context__ = context - te.exceptions = exceptions - if cause: - queue.append((te.__cause__, e.__cause__)) - if context: - queue.append((te.__context__, e.__context__)) - if exceptions: - queue.extend(zip(te.exceptions, e.exceptions)) - - def format(self, *, chain=True, _ctx=None, **kwargs): - if _ctx is None: - _ctx = _ExceptionPrintContext() - - output = [] - exc = self - if chain: - while exc: - if exc.__cause__ is not None: - chained_msg = _cause_message - chained_exc = exc.__cause__ - elif exc.__context__ is not None and not exc.__suppress_context__: - chained_msg = _context_message - chained_exc = exc.__context__ - else: - chained_msg = None - chained_exc = None - - output.append((chained_msg, exc)) - exc = chained_exc - else: - output.append((None, exc)) - - for msg, exc in reversed(output): - if msg is not None: - yield from _ctx.emit(msg) - if exc.exceptions is None: - if exc.stack: - yield from _ctx.emit("Traceback (most recent call last):\n") - yield from _ctx.emit(exc.stack.format()) - yield from _ctx.emit(exc.format_exception_only()) - elif _ctx.exception_group_depth > max_group_depth: - # exception group, but depth exceeds limit - yield from _ctx.emit(f"... (max_group_depth is {max_group_depth})\n") - else: - # format exception group - is_toplevel = _ctx.exception_group_depth == 0 - if is_toplevel: - _ctx.exception_group_depth += 1 - - if exc.stack: - yield from _ctx.emit( - "Exception Group Traceback (most recent call last):\n", - margin_char="+" if is_toplevel else None, - ) - yield from _ctx.emit(exc.stack.format()) - - yield from _ctx.emit(exc.format_exception_only()) - num_excs = len(exc.exceptions) - if num_excs <= max_group_width: - n = num_excs - else: - n = max_group_width + 1 - _ctx.need_close = False - for i in range(n): - last_exc = i == n - 1 - if last_exc: - # The closing frame may be added by a recursive call - _ctx.need_close = True - - if max_group_width is not None: - truncated = i >= max_group_width - else: - truncated = False - title = f"{i + 1}" if not truncated else "..." - yield ( - _ctx.indent() - + ("+-" if i == 0 else " ") - + f"+---------------- {title} ----------------\n" - ) - _ctx.exception_group_depth += 1 - if not truncated: - yield from exc.exceptions[i].format(chain=chain, _ctx=_ctx) - else: - remaining = num_excs - max_group_width - plural = "s" if remaining > 1 else "" - yield from _ctx.emit( - f"and {remaining} more exception{plural}\n" - ) - - if last_exc and _ctx.need_close: - yield _ctx.indent() + "+------------------------------------\n" - _ctx.need_close = False - _ctx.exception_group_depth -= 1 - - if is_toplevel: - assert _ctx.exception_group_depth == 1 - _ctx.exception_group_depth = 0 - - def format_exception_only(self, **kwargs): - """Format the exception part of the traceback. - The return value is a generator of strings, each ending in a newline. - Normally, the generator emits a single string; however, for - SyntaxError exceptions, it emits several lines that (when - printed) display detailed information about where the syntax - error occurred. - The message indicating which exception occurred is always the last - string in the output. - """ - if self.exc_type is None: - yield traceback._format_final_exc_line(None, self._str) - return - - stype = self.exc_type.__qualname__ - smod = self.exc_type.__module__ - if smod not in ("__main__", "builtins"): - if not isinstance(smod, str): - smod = "" - stype = smod + "." + stype - - if not issubclass(self.exc_type, SyntaxError): - yield _format_final_exc_line(stype, self._str) - elif traceback_exception_format_syntax_error is not None: - yield from traceback_exception_format_syntax_error(self, stype) - else: - yield from traceback_exception_original_format_exception_only(self) - - if isinstance(self.__notes__, collections.abc.Sequence): - for note in self.__notes__: - note = _safe_string(note, "note") - yield from [line + "\n" for line in note.split("\n")] - elif self.__notes__ is not None: - yield _safe_string(self.__notes__, "__notes__", func=repr) - - -traceback_exception_original_format = traceback.TracebackException.format -traceback_exception_original_format_exception_only = ( - traceback.TracebackException.format_exception_only -) -traceback_exception_format_syntax_error = getattr( - traceback.TracebackException, "_format_syntax_error", None -) -if sys.excepthook is sys.__excepthook__: - traceback.TracebackException.__init__ = ( # type: ignore[assignment] - PatchedTracebackException.__init__ - ) - traceback.TracebackException.format = ( # type: ignore[assignment] - PatchedTracebackException.format - ) - traceback.TracebackException.format_exception_only = ( # type: ignore[assignment] - PatchedTracebackException.format_exception_only - ) - sys.excepthook = exceptiongroup_excepthook - -# Ubuntu's system Python has a sitecustomize.py file that imports -# apport_python_hook and replaces sys.excepthook. -# -# The custom hook captures the error for crash reporting, and then calls -# sys.__excepthook__ to actually print the error. -# -# We don't mind it capturing the error for crash reporting, but we want to -# take over printing the error. So we monkeypatch the apport_python_hook -# module so that instead of calling sys.__excepthook__, it calls our custom -# hook. -# -# More details: https://github.com/python-trio/trio/issues/1065 -if getattr(sys.excepthook, "__name__", None) in ( - "apport_excepthook", - # on ubuntu 22.10 the hook was renamed to partial_apport_excepthook - "partial_apport_excepthook", -): - # patch traceback like above - traceback.TracebackException.__init__ = ( # type: ignore[assignment] - PatchedTracebackException.__init__ - ) - traceback.TracebackException.format = ( # type: ignore[assignment] - PatchedTracebackException.format - ) - traceback.TracebackException.format_exception_only = ( # type: ignore[assignment] - PatchedTracebackException.format_exception_only - ) - - from types import ModuleType - - import apport_python_hook - - # monkeypatch the sys module that apport has imported - fake_sys = ModuleType("exceptiongroup_fake_sys") - fake_sys.__dict__.update(sys.__dict__) - fake_sys.__excepthook__ = exceptiongroup_excepthook - apport_python_hook.sys = fake_sys - - -@singledispatch -def format_exception_only(__exc: BaseException, **kwargs: Any) -> List[str]: - return list( - PatchedTracebackException( - type(__exc), __exc, None, compact=True - ).format_exception_only() - ) - - -@format_exception_only.register -def _(__exc: type, value: BaseException, **kwargs: Any) -> List[str]: - return format_exception_only(value) - - -@singledispatch -def format_exception( - __exc: BaseException, limit: Optional[int] = None, chain: bool = True, **kwargs: Any -) -> List[str]: - return list( - PatchedTracebackException( - type(__exc), __exc, __exc.__traceback__, limit=limit, compact=True - ).format(chain=chain) - ) - - -@format_exception.register -def _( - __exc: type, - value: BaseException, - tb: TracebackType, - limit: Optional[int] = None, - chain: bool = True, - **kwargs: Any, -) -> List[str]: - return format_exception(value, limit, chain) - - -@singledispatch -def print_exception( - __exc: BaseException, - limit: Optional[int] = None, - file: Any = None, - chain: bool = True, - **kwargs: Any, -) -> None: - if file is None: - file = sys.stderr - - for line in PatchedTracebackException( - type(__exc), __exc, __exc.__traceback__, limit=limit - ).format(chain=chain): - print(line, file=file, end="") - - -@print_exception.register -def _( - __exc: type, - value: BaseException, - tb: TracebackType, - limit: Optional[int] = None, - file: Any = None, - chain: bool = True, -) -> None: - print_exception(value, limit, file, chain) - - -def print_exc( - limit: Optional[int] = None, - file: Any | None = None, - chain: bool = True, -) -> None: - value = sys.exc_info()[1] - print_exception(value, limit, file, chain) - - -# Python levenshtein edit distance code for NameError/AttributeError -# suggestions, backported from 3.12 - -_MAX_CANDIDATE_ITEMS = 750 -_MAX_STRING_SIZE = 40 -_MOVE_COST = 2 -_CASE_COST = 1 -_SENTINEL = object() - - -def _substitution_cost(ch_a, ch_b): - if ch_a == ch_b: - return 0 - if ch_a.lower() == ch_b.lower(): - return _CASE_COST - return _MOVE_COST - - -def _compute_suggestion_error(exc_value, tb): - wrong_name = getattr(exc_value, "name", None) - if wrong_name is None or not isinstance(wrong_name, str): - return None - if isinstance(exc_value, AttributeError): - obj = getattr(exc_value, "obj", _SENTINEL) - if obj is _SENTINEL: - return None - obj = exc_value.obj - try: - d = dir(obj) - except Exception: - return None - else: - assert isinstance(exc_value, NameError) - # find most recent frame - if tb is None: - return None - while tb.tb_next is not None: - tb = tb.tb_next - frame = tb.tb_frame - - d = list(frame.f_locals) + list(frame.f_globals) + list(frame.f_builtins) - if len(d) > _MAX_CANDIDATE_ITEMS: - return None - wrong_name_len = len(wrong_name) - if wrong_name_len > _MAX_STRING_SIZE: - return None - best_distance = wrong_name_len - suggestion = None - for possible_name in d: - if possible_name == wrong_name: - # A missing attribute is "found". Don't suggest it (see GH-88821). - continue - # No more than 1/3 of the involved characters should need changed. - max_distance = (len(possible_name) + wrong_name_len + 3) * _MOVE_COST // 6 - # Don't take matches we've already beaten. - max_distance = min(max_distance, best_distance - 1) - current_distance = _levenshtein_distance( - wrong_name, possible_name, max_distance - ) - if current_distance > max_distance: - continue - if not suggestion or current_distance < best_distance: - suggestion = possible_name - best_distance = current_distance - return suggestion - - -def _levenshtein_distance(a, b, max_cost): - # A Python implementation of Python/suggestions.c:levenshtein_distance. - - # Both strings are the same - if a == b: - return 0 - - # Trim away common affixes - pre = 0 - while a[pre:] and b[pre:] and a[pre] == b[pre]: - pre += 1 - a = a[pre:] - b = b[pre:] - post = 0 - while a[: post or None] and b[: post or None] and a[post - 1] == b[post - 1]: - post -= 1 - a = a[: post or None] - b = b[: post or None] - if not a or not b: - return _MOVE_COST * (len(a) + len(b)) - if len(a) > _MAX_STRING_SIZE or len(b) > _MAX_STRING_SIZE: - return max_cost + 1 - - # Prefer shorter buffer - if len(b) < len(a): - a, b = b, a - - # Quick fail when a match is impossible - if (len(b) - len(a)) * _MOVE_COST > max_cost: - return max_cost + 1 - - # Instead of producing the whole traditional len(a)-by-len(b) - # matrix, we can update just one row in place. - # Initialize the buffer row - row = list(range(_MOVE_COST, _MOVE_COST * (len(a) + 1), _MOVE_COST)) - - result = 0 - for bindex in range(len(b)): - bchar = b[bindex] - distance = result = bindex * _MOVE_COST - minimum = sys.maxsize - for index in range(len(a)): - # 1) Previous distance in this row is cost(b[:b_index], a[:index]) - substitute = distance + _substitution_cost(bchar, a[index]) - # 2) cost(b[:b_index], a[:index+1]) from previous row - distance = row[index] - # 3) existing result is cost(b[:b_index+1], a[index]) - - insert_delete = min(result, distance) + _MOVE_COST - result = min(insert_delete, substitute) - - # cost(b[:b_index+1], a[:index+1]) - row[index] = result - if result < minimum: - minimum = result - if minimum > max_cost: - # Everything in this row is too big, so bail early. - return max_cost + 1 - return result diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup/_suppress.py b/serverenv/lib/python3.9/site-packages/exceptiongroup/_suppress.py deleted file mode 100644 index 11467ee..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup/_suppress.py +++ /dev/null @@ -1,55 +0,0 @@ -from __future__ import annotations - -import sys -from contextlib import AbstractContextManager -from types import TracebackType -from typing import TYPE_CHECKING, Optional, Type, cast - -if sys.version_info < (3, 11): - from ._exceptions import BaseExceptionGroup - -if TYPE_CHECKING: - # requires python 3.9 - BaseClass = AbstractContextManager[None] -else: - BaseClass = AbstractContextManager - - -class suppress(BaseClass): - """Backport of :class:`contextlib.suppress` from Python 3.12.1.""" - - def __init__(self, *exceptions: type[BaseException]): - self._exceptions = exceptions - - def __enter__(self) -> None: - pass - - def __exit__( - self, - exctype: Optional[Type[BaseException]], - excinst: Optional[BaseException], - exctb: Optional[TracebackType], - ) -> bool: - # Unlike isinstance and issubclass, CPython exception handling - # currently only looks at the concrete type hierarchy (ignoring - # the instance and subclass checking hooks). While Guido considers - # that a bug rather than a feature, it's a fairly hard one to fix - # due to various internal implementation details. suppress provides - # the simpler issubclass based semantics, rather than trying to - # exactly reproduce the limitations of the CPython interpreter. - # - # See http://bugs.python.org/issue12029 for more details - if exctype is None: - return False - - if issubclass(exctype, self._exceptions): - return True - - if issubclass(exctype, BaseExceptionGroup): - match, rest = cast(BaseExceptionGroup, excinst).split(self._exceptions) - if rest is None: - return True - - raise rest - - return False diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup/_version.py b/serverenv/lib/python3.9/site-packages/exceptiongroup/_version.py deleted file mode 100644 index 32c340d..0000000 --- a/serverenv/lib/python3.9/site-packages/exceptiongroup/_version.py +++ /dev/null @@ -1,21 +0,0 @@ -# file generated by setuptools-scm -# don't change, don't track in version control - -__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"] - -TYPE_CHECKING = False -if TYPE_CHECKING: - from typing import Tuple - from typing import Union - - VERSION_TUPLE = Tuple[Union[int, str], ...] -else: - VERSION_TUPLE = object - -version: str -__version__: str -__version_tuple__: VERSION_TUPLE -version_tuple: VERSION_TUPLE - -__version__ = version = '1.3.0' -__version_tuple__ = version_tuple = (1, 3, 0) diff --git a/serverenv/lib/python3.9/site-packages/exceptiongroup/py.typed b/serverenv/lib/python3.9/site-packages/exceptiongroup/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/METADATA deleted file mode 100644 index 42ce213..0000000 --- a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/METADATA +++ /dev/null @@ -1,89 +0,0 @@ -Metadata-Version: 2.4 -Name: Flask -Version: 3.1.1 -Summary: A simple framework for building complex web applications. -Maintainer-email: Pallets -Requires-Python: >=3.9 -Description-Content-Type: text/markdown -License-Expression: BSD-3-Clause -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Framework :: Flask -Classifier: Intended Audience :: Developers -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application -Classifier: Topic :: Software Development :: Libraries :: Application Frameworks -Classifier: Typing :: Typed -License-File: LICENSE.txt -Requires-Dist: blinker>=1.9.0 -Requires-Dist: click>=8.1.3 -Requires-Dist: importlib-metadata>=3.6.0; python_version < '3.10' -Requires-Dist: itsdangerous>=2.2.0 -Requires-Dist: jinja2>=3.1.2 -Requires-Dist: markupsafe>=2.1.1 -Requires-Dist: werkzeug>=3.1.0 -Requires-Dist: asgiref>=3.2 ; extra == "async" -Requires-Dist: python-dotenv ; extra == "dotenv" -Project-URL: Changes, https://flask.palletsprojects.com/page/changes/ -Project-URL: Chat, https://discord.gg/pallets -Project-URL: Documentation, https://flask.palletsprojects.com/ -Project-URL: Donate, https://palletsprojects.com/donate -Project-URL: Source, https://github.com/pallets/flask/ -Provides-Extra: async -Provides-Extra: dotenv - -# Flask - -Flask is a lightweight [WSGI] web application framework. It is designed -to make getting started quick and easy, with the ability to scale up to -complex applications. It began as a simple wrapper around [Werkzeug] -and [Jinja], and has become one of the most popular Python web -application frameworks. - -Flask offers suggestions, but doesn't enforce any dependencies or -project layout. It is up to the developer to choose the tools and -libraries they want to use. There are many extensions provided by the -community that make adding new functionality easy. - -[WSGI]: https://wsgi.readthedocs.io/ -[Werkzeug]: https://werkzeug.palletsprojects.com/ -[Jinja]: https://jinja.palletsprojects.com/ - -## A Simple Example - -```python -# save this as app.py -from flask import Flask - -app = Flask(__name__) - -@app.route("/") -def hello(): - return "Hello, World!" -``` - -``` -$ flask run - * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) -``` - -## Donate - -The Pallets organization develops and supports Flask and the libraries -it uses. In order to grow the community of contributors and users, and -allow the maintainers to devote more time to the projects, [please -donate today]. - -[please donate today]: https://palletsprojects.com/donate - -## Contributing - -See our [detailed contributing documentation][contrib] for many ways to -contribute, including reporting issues, requesting features, asking or answering -questions, and making PRs. - -[contrib]: https://palletsprojects.com/contributing/ - diff --git a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/RECORD deleted file mode 100644 index 545903b..0000000 --- a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/RECORD +++ /dev/null @@ -1,57 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/__main__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/app.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/blueprints.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/cli.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/config.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/ctx.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/debughelpers.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/globals.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/helpers.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/json/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/json/provider.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/json/tag.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/logging.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/sansio/app.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/sansio/blueprints.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/sansio/scaffold.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/sessions.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/signals.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/templating.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/testing.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/typing.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/views.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/flask/wrappers.cpython-39.pyc,, -../../../bin/flask,sha256=stOc4wDOUp64J1rCfeVxWcsQRuGaIGH3F3dP43JYxGs,243 -flask-3.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -flask-3.1.1.dist-info/METADATA,sha256=EsnOyVfBXjw1BkGn-9lrI5mcv1NwYyB4_CfdW2FSDZQ,3014 -flask-3.1.1.dist-info/RECORD,, -flask-3.1.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 -flask-3.1.1.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40 -flask-3.1.1.dist-info/licenses/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 -flask/__init__.py,sha256=mHvJN9Swtl1RDtjCqCIYyIniK_SZ_l_hqUynOzgpJ9o,2701 -flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 -flask/app.py,sha256=XGqgFRsLgBhzIoB2HSftoMTIM3hjDiH6rdV7c3g3IKc,61744 -flask/blueprints.py,sha256=p5QE2lY18GItbdr_RKRpZ8Do17g0PvQGIgZkSUDhX2k,4541 -flask/cli.py,sha256=Pfh72-BxlvoH0QHCDOc1HvXG7Kq5Xetf3zzNz2kNSHk,37184 -flask/config.py,sha256=PiqF0DPam6HW0FH4CH1hpXTBe30NSzjPEOwrz1b6kt0,13219 -flask/ctx.py,sha256=4atDhJJ_cpV1VMq4qsfU4E_61M1oN93jlS2H9gjrl58,15120 -flask/debughelpers.py,sha256=PGIDhStW_efRjpaa3zHIpo-htStJOR41Ip3OJWPYBwo,6080 -flask/globals.py,sha256=XdQZmStBmPIs8t93tjx6pO7Bm3gobAaONWkFcUHaGas,1713 -flask/helpers.py,sha256=7njmzkFJvrPSQudsgONsgQzaGrGppeBINevKgWescPk,23521 -flask/json/__init__.py,sha256=hLNR898paqoefdeAhraa5wyJy-bmRB2k2dV4EgVy2Z8,5602 -flask/json/provider.py,sha256=5imEzY5HjV2HoUVrQbJLqXCzMNpZXfD0Y1XqdLV2XBA,7672 -flask/json/tag.py,sha256=DhaNwuIOhdt2R74oOC9Y4Z8ZprxFYiRb5dUP5byyINw,9281 -flask/logging.py,sha256=8sM3WMTubi1cBb2c_lPkWpN0J8dMAqrgKRYLLi1dCVI,2377 -flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -flask/sansio/README.md,sha256=-0X1tECnilmz1cogx-YhNw5d7guK7GKrq_DEV2OzlU0,228 -flask/sansio/app.py,sha256=Wj9NVGtiR1jvkZ9gSFd91usUlM8H0g06aPVz2sMh4bw,38116 -flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637 -flask/sansio/scaffold.py,sha256=q6wM4Y4aYMGGN_Litsj3PYKpBS3Zvut0xhDmpBEHFdo,30387 -flask/sessions.py,sha256=ED_OV3Jl1emsy7Zntb7aFWxyoynt-PzNY0eFUH-Syo0,15495 -flask/signals.py,sha256=V7lMUww7CqgJ2ThUBn1PiatZtQanOyt7OZpu2GZI-34,750 -flask/templating.py,sha256=2TcXLT85Asflm2W9WOSFxKCmYn5e49w_Jkg9-NaaJWo,7537 -flask/testing.py,sha256=JT9fi_-_qsAXIpC1NSWcp1VrO-QSXgmdq95extfCwEw,10136 -flask/typing.py,sha256=L-L5t2jKgS0aOmVhioQ_ylqcgiVFnA6yxO-RLNhq-GU,3293 -flask/views.py,sha256=xzJx6oJqGElThtEghZN7ZQGMw5TDFyuRxUkecwRuAoA,6962 -flask/wrappers.py,sha256=jUkv4mVek2Iq4hwxd4RvqrIMb69Bv0PElDgWLmd5ORo,9406 diff --git a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/WHEEL deleted file mode 100644 index d8b9936..0000000 --- a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.12.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/entry_points.txt b/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/entry_points.txt deleted file mode 100644 index eec6733..0000000 --- a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -flask=flask.cli:main - diff --git a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/licenses/LICENSE.txt b/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/licenses/LICENSE.txt deleted file mode 100644 index 9d227a0..0000000 --- a/serverenv/lib/python3.9/site-packages/flask-3.1.1.dist-info/licenses/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2010 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/serverenv/lib/python3.9/site-packages/flask/__init__.py b/serverenv/lib/python3.9/site-packages/flask/__init__.py deleted file mode 100644 index 1fdc50c..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/__init__.py +++ /dev/null @@ -1,61 +0,0 @@ -from __future__ import annotations - -import typing as t - -from . import json as json -from .app import Flask as Flask -from .blueprints import Blueprint as Blueprint -from .config import Config as Config -from .ctx import after_this_request as after_this_request -from .ctx import copy_current_request_context as copy_current_request_context -from .ctx import has_app_context as has_app_context -from .ctx import has_request_context as has_request_context -from .globals import current_app as current_app -from .globals import g as g -from .globals import request as request -from .globals import session as session -from .helpers import abort as abort -from .helpers import flash as flash -from .helpers import get_flashed_messages as get_flashed_messages -from .helpers import get_template_attribute as get_template_attribute -from .helpers import make_response as make_response -from .helpers import redirect as redirect -from .helpers import send_file as send_file -from .helpers import send_from_directory as send_from_directory -from .helpers import stream_with_context as stream_with_context -from .helpers import url_for as url_for -from .json import jsonify as jsonify -from .signals import appcontext_popped as appcontext_popped -from .signals import appcontext_pushed as appcontext_pushed -from .signals import appcontext_tearing_down as appcontext_tearing_down -from .signals import before_render_template as before_render_template -from .signals import got_request_exception as got_request_exception -from .signals import message_flashed as message_flashed -from .signals import request_finished as request_finished -from .signals import request_started as request_started -from .signals import request_tearing_down as request_tearing_down -from .signals import template_rendered as template_rendered -from .templating import render_template as render_template -from .templating import render_template_string as render_template_string -from .templating import stream_template as stream_template -from .templating import stream_template_string as stream_template_string -from .wrappers import Request as Request -from .wrappers import Response as Response - -if not t.TYPE_CHECKING: - - def __getattr__(name: str) -> t.Any: - if name == "__version__": - import importlib.metadata - import warnings - - warnings.warn( - "The '__version__' attribute is deprecated and will be removed in" - " Flask 3.2. Use feature detection or" - " 'importlib.metadata.version(\"flask\")' instead.", - DeprecationWarning, - stacklevel=2, - ) - return importlib.metadata.version("flask") - - raise AttributeError(name) diff --git a/serverenv/lib/python3.9/site-packages/flask/__main__.py b/serverenv/lib/python3.9/site-packages/flask/__main__.py deleted file mode 100644 index 4e28416..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .cli import main - -main() diff --git a/serverenv/lib/python3.9/site-packages/flask/app.py b/serverenv/lib/python3.9/site-packages/flask/app.py deleted file mode 100644 index 1232b03..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/app.py +++ /dev/null @@ -1,1536 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import os -import sys -import typing as t -import weakref -from datetime import timedelta -from inspect import iscoroutinefunction -from itertools import chain -from types import TracebackType -from urllib.parse import quote as _url_quote - -import click -from werkzeug.datastructures import Headers -from werkzeug.datastructures import ImmutableDict -from werkzeug.exceptions import BadRequestKeyError -from werkzeug.exceptions import HTTPException -from werkzeug.exceptions import InternalServerError -from werkzeug.routing import BuildError -from werkzeug.routing import MapAdapter -from werkzeug.routing import RequestRedirect -from werkzeug.routing import RoutingException -from werkzeug.routing import Rule -from werkzeug.serving import is_running_from_reloader -from werkzeug.wrappers import Response as BaseResponse -from werkzeug.wsgi import get_host - -from . import cli -from . import typing as ft -from .ctx import AppContext -from .ctx import RequestContext -from .globals import _cv_app -from .globals import _cv_request -from .globals import current_app -from .globals import g -from .globals import request -from .globals import request_ctx -from .globals import session -from .helpers import get_debug_flag -from .helpers import get_flashed_messages -from .helpers import get_load_dotenv -from .helpers import send_from_directory -from .sansio.app import App -from .sansio.scaffold import _sentinel -from .sessions import SecureCookieSessionInterface -from .sessions import SessionInterface -from .signals import appcontext_tearing_down -from .signals import got_request_exception -from .signals import request_finished -from .signals import request_started -from .signals import request_tearing_down -from .templating import Environment -from .wrappers import Request -from .wrappers import Response - -if t.TYPE_CHECKING: # pragma: no cover - from _typeshed.wsgi import StartResponse - from _typeshed.wsgi import WSGIEnvironment - - from .testing import FlaskClient - from .testing import FlaskCliRunner - from .typing import HeadersValue - -T_shell_context_processor = t.TypeVar( - "T_shell_context_processor", bound=ft.ShellContextProcessorCallable -) -T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) -T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) -T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) -T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) - - -def _make_timedelta(value: timedelta | int | None) -> timedelta | None: - if value is None or isinstance(value, timedelta): - return value - - return timedelta(seconds=value) - - -class Flask(App): - """The flask object implements a WSGI application and acts as the central - object. It is passed the name of the module or package of the - application. Once it is created it will act as a central registry for - the view functions, the URL rules, template configuration and much more. - - The name of the package is used to resolve resources from inside the - package or the folder the module is contained in depending on if the - package parameter resolves to an actual python package (a folder with - an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). - - For more information about resource loading, see :func:`open_resource`. - - Usually you create a :class:`Flask` instance in your main module or - in the :file:`__init__.py` file of your package like this:: - - from flask import Flask - app = Flask(__name__) - - .. admonition:: About the First Parameter - - The idea of the first parameter is to give Flask an idea of what - belongs to your application. This name is used to find resources - on the filesystem, can be used by extensions to improve debugging - information and a lot more. - - So it's important what you provide there. If you are using a single - module, `__name__` is always the correct value. If you however are - using a package, it's usually recommended to hardcode the name of - your package there. - - For example if your application is defined in :file:`yourapplication/app.py` - you should create it with one of the two versions below:: - - app = Flask('yourapplication') - app = Flask(__name__.split('.')[0]) - - Why is that? The application will work even with `__name__`, thanks - to how resources are looked up. However it will make debugging more - painful. Certain extensions can make assumptions based on the - import name of your application. For example the Flask-SQLAlchemy - extension will look for the code in your application that triggered - an SQL query in debug mode. If the import name is not properly set - up, that debugging information is lost. (For example it would only - pick up SQL queries in `yourapplication.app` and not - `yourapplication.views.frontend`) - - .. versionadded:: 0.7 - The `static_url_path`, `static_folder`, and `template_folder` - parameters were added. - - .. versionadded:: 0.8 - The `instance_path` and `instance_relative_config` parameters were - added. - - .. versionadded:: 0.11 - The `root_path` parameter was added. - - .. versionadded:: 1.0 - The ``host_matching`` and ``static_host`` parameters were added. - - .. versionadded:: 1.0 - The ``subdomain_matching`` parameter was added. Subdomain - matching needs to be enabled manually now. Setting - :data:`SERVER_NAME` does not implicitly enable it. - - :param import_name: the name of the application package - :param static_url_path: can be used to specify a different path for the - static files on the web. Defaults to the name - of the `static_folder` folder. - :param static_folder: The folder with static files that is served at - ``static_url_path``. Relative to the application ``root_path`` - or an absolute path. Defaults to ``'static'``. - :param static_host: the host to use when adding the static route. - Defaults to None. Required when using ``host_matching=True`` - with a ``static_folder`` configured. - :param host_matching: set ``url_map.host_matching`` attribute. - Defaults to False. - :param subdomain_matching: consider the subdomain relative to - :data:`SERVER_NAME` when matching routes. Defaults to False. - :param template_folder: the folder that contains the templates that should - be used by the application. Defaults to - ``'templates'`` folder in the root path of the - application. - :param instance_path: An alternative instance path for the application. - By default the folder ``'instance'`` next to the - package or module is assumed to be the instance - path. - :param instance_relative_config: if set to ``True`` relative filenames - for loading the config are assumed to - be relative to the instance path instead - of the application root. - :param root_path: The path to the root of the application files. - This should only be set manually when it can't be detected - automatically, such as for namespace packages. - """ - - default_config = ImmutableDict( - { - "DEBUG": None, - "TESTING": False, - "PROPAGATE_EXCEPTIONS": None, - "SECRET_KEY": None, - "SECRET_KEY_FALLBACKS": None, - "PERMANENT_SESSION_LIFETIME": timedelta(days=31), - "USE_X_SENDFILE": False, - "TRUSTED_HOSTS": None, - "SERVER_NAME": None, - "APPLICATION_ROOT": "/", - "SESSION_COOKIE_NAME": "session", - "SESSION_COOKIE_DOMAIN": None, - "SESSION_COOKIE_PATH": None, - "SESSION_COOKIE_HTTPONLY": True, - "SESSION_COOKIE_SECURE": False, - "SESSION_COOKIE_PARTITIONED": False, - "SESSION_COOKIE_SAMESITE": None, - "SESSION_REFRESH_EACH_REQUEST": True, - "MAX_CONTENT_LENGTH": None, - "MAX_FORM_MEMORY_SIZE": 500_000, - "MAX_FORM_PARTS": 1_000, - "SEND_FILE_MAX_AGE_DEFAULT": None, - "TRAP_BAD_REQUEST_ERRORS": None, - "TRAP_HTTP_EXCEPTIONS": False, - "EXPLAIN_TEMPLATE_LOADING": False, - "PREFERRED_URL_SCHEME": "http", - "TEMPLATES_AUTO_RELOAD": None, - "MAX_COOKIE_SIZE": 4093, - "PROVIDE_AUTOMATIC_OPTIONS": True, - } - ) - - #: The class that is used for request objects. See :class:`~flask.Request` - #: for more information. - request_class: type[Request] = Request - - #: The class that is used for response objects. See - #: :class:`~flask.Response` for more information. - response_class: type[Response] = Response - - #: the session interface to use. By default an instance of - #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. - #: - #: .. versionadded:: 0.8 - session_interface: SessionInterface = SecureCookieSessionInterface() - - def __init__( - self, - import_name: str, - static_url_path: str | None = None, - static_folder: str | os.PathLike[str] | None = "static", - static_host: str | None = None, - host_matching: bool = False, - subdomain_matching: bool = False, - template_folder: str | os.PathLike[str] | None = "templates", - instance_path: str | None = None, - instance_relative_config: bool = False, - root_path: str | None = None, - ): - super().__init__( - import_name=import_name, - static_url_path=static_url_path, - static_folder=static_folder, - static_host=static_host, - host_matching=host_matching, - subdomain_matching=subdomain_matching, - template_folder=template_folder, - instance_path=instance_path, - instance_relative_config=instance_relative_config, - root_path=root_path, - ) - - #: The Click command group for registering CLI commands for this - #: object. The commands are available from the ``flask`` command - #: once the application has been discovered and blueprints have - #: been registered. - self.cli = cli.AppGroup() - - # Set the name of the Click group in case someone wants to add - # the app's commands to another CLI tool. - self.cli.name = self.name - - # Add a static route using the provided static_url_path, static_host, - # and static_folder if there is a configured static_folder. - # Note we do this without checking if static_folder exists. - # For one, it might be created while the server is running (e.g. during - # development). Also, Google App Engine stores static files somewhere - if self.has_static_folder: - assert bool(static_host) == host_matching, ( - "Invalid static_host/host_matching combination" - ) - # Use a weakref to avoid creating a reference cycle between the app - # and the view function (see #3761). - self_ref = weakref.ref(self) - self.add_url_rule( - f"{self.static_url_path}/", - endpoint="static", - host=static_host, - view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 - ) - - def get_send_file_max_age(self, filename: str | None) -> int | None: - """Used by :func:`send_file` to determine the ``max_age`` cache - value for a given file path if it wasn't passed. - - By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from - the configuration of :data:`~flask.current_app`. This defaults - to ``None``, which tells the browser to use conditional requests - instead of a timed cache, which is usually preferable. - - Note this is a duplicate of the same method in the Flask - class. - - .. versionchanged:: 2.0 - The default configuration is ``None`` instead of 12 hours. - - .. versionadded:: 0.9 - """ - value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] - - if value is None: - return None - - if isinstance(value, timedelta): - return int(value.total_seconds()) - - return value # type: ignore[no-any-return] - - def send_static_file(self, filename: str) -> Response: - """The view function used to serve files from - :attr:`static_folder`. A route is automatically registered for - this view at :attr:`static_url_path` if :attr:`static_folder` is - set. - - Note this is a duplicate of the same method in the Flask - class. - - .. versionadded:: 0.5 - - """ - if not self.has_static_folder: - raise RuntimeError("'static_folder' must be set to serve static_files.") - - # send_file only knows to call get_send_file_max_age on the app, - # call it here so it works for blueprints too. - max_age = self.get_send_file_max_age(filename) - return send_from_directory( - t.cast(str, self.static_folder), filename, max_age=max_age - ) - - def open_resource( - self, resource: str, mode: str = "rb", encoding: str | None = None - ) -> t.IO[t.AnyStr]: - """Open a resource file relative to :attr:`root_path` for reading. - - For example, if the file ``schema.sql`` is next to the file - ``app.py`` where the ``Flask`` app is defined, it can be opened - with: - - .. code-block:: python - - with app.open_resource("schema.sql") as f: - conn.executescript(f.read()) - - :param resource: Path to the resource relative to :attr:`root_path`. - :param mode: Open the file in this mode. Only reading is supported, - valid values are ``"r"`` (or ``"rt"``) and ``"rb"``. - :param encoding: Open the file with this encoding when opening in text - mode. This is ignored when opening in binary mode. - - .. versionchanged:: 3.1 - Added the ``encoding`` parameter. - """ - if mode not in {"r", "rt", "rb"}: - raise ValueError("Resources can only be opened for reading.") - - path = os.path.join(self.root_path, resource) - - if mode == "rb": - return open(path, mode) # pyright: ignore - - return open(path, mode, encoding=encoding) - - def open_instance_resource( - self, resource: str, mode: str = "rb", encoding: str | None = "utf-8" - ) -> t.IO[t.AnyStr]: - """Open a resource file relative to the application's instance folder - :attr:`instance_path`. Unlike :meth:`open_resource`, files in the - instance folder can be opened for writing. - - :param resource: Path to the resource relative to :attr:`instance_path`. - :param mode: Open the file in this mode. - :param encoding: Open the file with this encoding when opening in text - mode. This is ignored when opening in binary mode. - - .. versionchanged:: 3.1 - Added the ``encoding`` parameter. - """ - path = os.path.join(self.instance_path, resource) - - if "b" in mode: - return open(path, mode) - - return open(path, mode, encoding=encoding) - - def create_jinja_environment(self) -> Environment: - """Create the Jinja environment based on :attr:`jinja_options` - and the various Jinja-related methods of the app. Changing - :attr:`jinja_options` after this will have no effect. Also adds - Flask-related globals and filters to the environment. - - .. versionchanged:: 0.11 - ``Environment.auto_reload`` set in accordance with - ``TEMPLATES_AUTO_RELOAD`` configuration option. - - .. versionadded:: 0.5 - """ - options = dict(self.jinja_options) - - if "autoescape" not in options: - options["autoescape"] = self.select_jinja_autoescape - - if "auto_reload" not in options: - auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] - - if auto_reload is None: - auto_reload = self.debug - - options["auto_reload"] = auto_reload - - rv = self.jinja_environment(self, **options) - rv.globals.update( - url_for=self.url_for, - get_flashed_messages=get_flashed_messages, - config=self.config, - # request, session and g are normally added with the - # context processor for efficiency reasons but for imported - # templates we also want the proxies in there. - request=request, - session=session, - g=g, - ) - rv.policies["json.dumps_function"] = self.json.dumps - return rv - - def create_url_adapter(self, request: Request | None) -> MapAdapter | None: - """Creates a URL adapter for the given request. The URL adapter - is created at a point where the request context is not yet set - up so the request is passed explicitly. - - .. versionchanged:: 3.1 - If :data:`SERVER_NAME` is set, it does not restrict requests to - only that domain, for both ``subdomain_matching`` and - ``host_matching``. - - .. versionchanged:: 1.0 - :data:`SERVER_NAME` no longer implicitly enables subdomain - matching. Use :attr:`subdomain_matching` instead. - - .. versionchanged:: 0.9 - This can be called outside a request when the URL adapter is created - for an application context. - - .. versionadded:: 0.6 - """ - if request is not None: - if (trusted_hosts := self.config["TRUSTED_HOSTS"]) is not None: - request.trusted_hosts = trusted_hosts - - # Check trusted_hosts here until bind_to_environ does. - request.host = get_host(request.environ, request.trusted_hosts) # pyright: ignore - subdomain = None - server_name = self.config["SERVER_NAME"] - - if self.url_map.host_matching: - # Don't pass SERVER_NAME, otherwise it's used and the actual - # host is ignored, which breaks host matching. - server_name = None - elif not self.subdomain_matching: - # Werkzeug doesn't implement subdomain matching yet. Until then, - # disable it by forcing the current subdomain to the default, or - # the empty string. - subdomain = self.url_map.default_subdomain or "" - - return self.url_map.bind_to_environ( - request.environ, server_name=server_name, subdomain=subdomain - ) - - # Need at least SERVER_NAME to match/build outside a request. - if self.config["SERVER_NAME"] is not None: - return self.url_map.bind( - self.config["SERVER_NAME"], - script_name=self.config["APPLICATION_ROOT"], - url_scheme=self.config["PREFERRED_URL_SCHEME"], - ) - - return None - - def raise_routing_exception(self, request: Request) -> t.NoReturn: - """Intercept routing exceptions and possibly do something else. - - In debug mode, intercept a routing redirect and replace it with - an error if the body will be discarded. - - With modern Werkzeug this shouldn't occur, since it now uses a - 308 status which tells the browser to resend the method and - body. - - .. versionchanged:: 2.1 - Don't intercept 307 and 308 redirects. - - :meta private: - :internal: - """ - if ( - not self.debug - or not isinstance(request.routing_exception, RequestRedirect) - or request.routing_exception.code in {307, 308} - or request.method in {"GET", "HEAD", "OPTIONS"} - ): - raise request.routing_exception # type: ignore[misc] - - from .debughelpers import FormDataRoutingRedirect - - raise FormDataRoutingRedirect(request) - - def update_template_context(self, context: dict[str, t.Any]) -> None: - """Update the template context with some commonly used variables. - This injects request, session, config and g into the template - context as well as everything template context processors want - to inject. Note that the as of Flask 0.6, the original values - in the context will not be overridden if a context processor - decides to return a value with the same key. - - :param context: the context as a dictionary that is updated in place - to add extra variables. - """ - names: t.Iterable[str | None] = (None,) - - # A template may be rendered outside a request context. - if request: - names = chain(names, reversed(request.blueprints)) - - # The values passed to render_template take precedence. Keep a - # copy to re-apply after all context functions. - orig_ctx = context.copy() - - for name in names: - if name in self.template_context_processors: - for func in self.template_context_processors[name]: - context.update(self.ensure_sync(func)()) - - context.update(orig_ctx) - - def make_shell_context(self) -> dict[str, t.Any]: - """Returns the shell context for an interactive shell for this - application. This runs all the registered shell context - processors. - - .. versionadded:: 0.11 - """ - rv = {"app": self, "g": g} - for processor in self.shell_context_processors: - rv.update(processor()) - return rv - - def run( - self, - host: str | None = None, - port: int | None = None, - debug: bool | None = None, - load_dotenv: bool = True, - **options: t.Any, - ) -> None: - """Runs the application on a local development server. - - Do not use ``run()`` in a production setting. It is not intended to - meet security and performance requirements for a production server. - Instead, see :doc:`/deploying/index` for WSGI server recommendations. - - If the :attr:`debug` flag is set the server will automatically reload - for code changes and show a debugger in case an exception happened. - - If you want to run the application in debug mode, but disable the - code execution on the interactive debugger, you can pass - ``use_evalex=False`` as parameter. This will keep the debugger's - traceback screen active, but disable code execution. - - It is not recommended to use this function for development with - automatic reloading as this is badly supported. Instead you should - be using the :command:`flask` command line script's ``run`` support. - - .. admonition:: Keep in Mind - - Flask will suppress any server error with a generic error page - unless it is in debug mode. As such to enable just the - interactive debugger without the code reloading, you have to - invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. - Setting ``use_debugger`` to ``True`` without being in debug mode - won't catch any exceptions because there won't be any to - catch. - - :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to - have the server available externally as well. Defaults to - ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable - if present. - :param port: the port of the webserver. Defaults to ``5000`` or the - port defined in the ``SERVER_NAME`` config variable if present. - :param debug: if given, enable or disable debug mode. See - :attr:`debug`. - :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` - files to set environment variables. Will also change the working - directory to the directory containing the first file found. - :param options: the options to be forwarded to the underlying Werkzeug - server. See :func:`werkzeug.serving.run_simple` for more - information. - - .. versionchanged:: 1.0 - If installed, python-dotenv will be used to load environment - variables from :file:`.env` and :file:`.flaskenv` files. - - The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`. - - Threaded mode is enabled by default. - - .. versionchanged:: 0.10 - The default port is now picked from the ``SERVER_NAME`` - variable. - """ - # Ignore this call so that it doesn't start another server if - # the 'flask run' command is used. - if os.environ.get("FLASK_RUN_FROM_CLI") == "true": - if not is_running_from_reloader(): - click.secho( - " * Ignoring a call to 'app.run()' that would block" - " the current 'flask' CLI command.\n" - " Only call 'app.run()' in an 'if __name__ ==" - ' "__main__"\' guard.', - fg="red", - ) - - return - - if get_load_dotenv(load_dotenv): - cli.load_dotenv() - - # if set, env var overrides existing value - if "FLASK_DEBUG" in os.environ: - self.debug = get_debug_flag() - - # debug passed to method overrides all other sources - if debug is not None: - self.debug = bool(debug) - - server_name = self.config.get("SERVER_NAME") - sn_host = sn_port = None - - if server_name: - sn_host, _, sn_port = server_name.partition(":") - - if not host: - if sn_host: - host = sn_host - else: - host = "127.0.0.1" - - if port or port == 0: - port = int(port) - elif sn_port: - port = int(sn_port) - else: - port = 5000 - - options.setdefault("use_reloader", self.debug) - options.setdefault("use_debugger", self.debug) - options.setdefault("threaded", True) - - cli.show_server_banner(self.debug, self.name) - - from werkzeug.serving import run_simple - - try: - run_simple(t.cast(str, host), port, self, **options) - finally: - # reset the first request information if the development server - # reset normally. This makes it possible to restart the server - # without reloader and that stuff from an interactive shell. - self._got_first_request = False - - def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> FlaskClient: - """Creates a test client for this application. For information - about unit testing head over to :doc:`/testing`. - - Note that if you are testing for assertions or exceptions in your - application code, you must set ``app.testing = True`` in order for the - exceptions to propagate to the test client. Otherwise, the exception - will be handled by the application (not visible to the test client) and - the only indication of an AssertionError or other exception will be a - 500 status code response to the test client. See the :attr:`testing` - attribute. For example:: - - app.testing = True - client = app.test_client() - - The test client can be used in a ``with`` block to defer the closing down - of the context until the end of the ``with`` block. This is useful if - you want to access the context locals for testing:: - - with app.test_client() as c: - rv = c.get('/?vodka=42') - assert request.args['vodka'] == '42' - - Additionally, you may pass optional keyword arguments that will then - be passed to the application's :attr:`test_client_class` constructor. - For example:: - - from flask.testing import FlaskClient - - class CustomClient(FlaskClient): - def __init__(self, *args, **kwargs): - self._authentication = kwargs.pop("authentication") - super(CustomClient,self).__init__( *args, **kwargs) - - app.test_client_class = CustomClient - client = app.test_client(authentication='Basic ....') - - See :class:`~flask.testing.FlaskClient` for more information. - - .. versionchanged:: 0.4 - added support for ``with`` block usage for the client. - - .. versionadded:: 0.7 - The `use_cookies` parameter was added as well as the ability - to override the client to be used by setting the - :attr:`test_client_class` attribute. - - .. versionchanged:: 0.11 - Added `**kwargs` to support passing additional keyword arguments to - the constructor of :attr:`test_client_class`. - """ - cls = self.test_client_class - if cls is None: - from .testing import FlaskClient as cls - return cls( # type: ignore - self, self.response_class, use_cookies=use_cookies, **kwargs - ) - - def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner: - """Create a CLI runner for testing CLI commands. - See :ref:`testing-cli`. - - Returns an instance of :attr:`test_cli_runner_class`, by default - :class:`~flask.testing.FlaskCliRunner`. The Flask app object is - passed as the first argument. - - .. versionadded:: 1.0 - """ - cls = self.test_cli_runner_class - - if cls is None: - from .testing import FlaskCliRunner as cls - - return cls(self, **kwargs) # type: ignore - - def handle_http_exception( - self, e: HTTPException - ) -> HTTPException | ft.ResponseReturnValue: - """Handles an HTTP exception. By default this will invoke the - registered error handlers and fall back to returning the - exception as response. - - .. versionchanged:: 1.0.3 - ``RoutingException``, used internally for actions such as - slash redirects during routing, is not passed to error - handlers. - - .. versionchanged:: 1.0 - Exceptions are looked up by code *and* by MRO, so - ``HTTPException`` subclasses can be handled with a catch-all - handler for the base ``HTTPException``. - - .. versionadded:: 0.3 - """ - # Proxy exceptions don't have error codes. We want to always return - # those unchanged as errors - if e.code is None: - return e - - # RoutingExceptions are used internally to trigger routing - # actions, such as slash redirects raising RequestRedirect. They - # are not raised or handled in user code. - if isinstance(e, RoutingException): - return e - - handler = self._find_error_handler(e, request.blueprints) - if handler is None: - return e - return self.ensure_sync(handler)(e) # type: ignore[no-any-return] - - def handle_user_exception( - self, e: Exception - ) -> HTTPException | ft.ResponseReturnValue: - """This method is called whenever an exception occurs that - should be handled. A special case is :class:`~werkzeug - .exceptions.HTTPException` which is forwarded to the - :meth:`handle_http_exception` method. This function will either - return a response value or reraise the exception with the same - traceback. - - .. versionchanged:: 1.0 - Key errors raised from request data like ``form`` show the - bad key in debug mode rather than a generic bad request - message. - - .. versionadded:: 0.7 - """ - if isinstance(e, BadRequestKeyError) and ( - self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"] - ): - e.show_exception = True - - if isinstance(e, HTTPException) and not self.trap_http_exception(e): - return self.handle_http_exception(e) - - handler = self._find_error_handler(e, request.blueprints) - - if handler is None: - raise - - return self.ensure_sync(handler)(e) # type: ignore[no-any-return] - - def handle_exception(self, e: Exception) -> Response: - """Handle an exception that did not have an error handler - associated with it, or that was raised from an error handler. - This always causes a 500 ``InternalServerError``. - - Always sends the :data:`got_request_exception` signal. - - If :data:`PROPAGATE_EXCEPTIONS` is ``True``, such as in debug - mode, the error will be re-raised so that the debugger can - display it. Otherwise, the original exception is logged, and - an :exc:`~werkzeug.exceptions.InternalServerError` is returned. - - If an error handler is registered for ``InternalServerError`` or - ``500``, it will be used. For consistency, the handler will - always receive the ``InternalServerError``. The original - unhandled exception is available as ``e.original_exception``. - - .. versionchanged:: 1.1.0 - Always passes the ``InternalServerError`` instance to the - handler, setting ``original_exception`` to the unhandled - error. - - .. versionchanged:: 1.1.0 - ``after_request`` functions and other finalization is done - even for the default 500 response when there is no handler. - - .. versionadded:: 0.3 - """ - exc_info = sys.exc_info() - got_request_exception.send(self, _async_wrapper=self.ensure_sync, exception=e) - propagate = self.config["PROPAGATE_EXCEPTIONS"] - - if propagate is None: - propagate = self.testing or self.debug - - if propagate: - # Re-raise if called with an active exception, otherwise - # raise the passed in exception. - if exc_info[1] is e: - raise - - raise e - - self.log_exception(exc_info) - server_error: InternalServerError | ft.ResponseReturnValue - server_error = InternalServerError(original_exception=e) - handler = self._find_error_handler(server_error, request.blueprints) - - if handler is not None: - server_error = self.ensure_sync(handler)(server_error) - - return self.finalize_request(server_error, from_error_handler=True) - - def log_exception( - self, - exc_info: (tuple[type, BaseException, TracebackType] | tuple[None, None, None]), - ) -> None: - """Logs an exception. This is called by :meth:`handle_exception` - if debugging is disabled and right before the handler is called. - The default implementation logs the exception as error on the - :attr:`logger`. - - .. versionadded:: 0.8 - """ - self.logger.error( - f"Exception on {request.path} [{request.method}]", exc_info=exc_info - ) - - def dispatch_request(self) -> ft.ResponseReturnValue: - """Does the request dispatching. Matches the URL and returns the - return value of the view or error handler. This does not have to - be a response object. In order to convert the return value to a - proper response object, call :func:`make_response`. - - .. versionchanged:: 0.7 - This no longer does the exception handling, this code was - moved to the new :meth:`full_dispatch_request`. - """ - req = request_ctx.request - if req.routing_exception is not None: - self.raise_routing_exception(req) - rule: Rule = req.url_rule # type: ignore[assignment] - # if we provide automatic options for this URL and the - # request came with the OPTIONS method, reply automatically - if ( - getattr(rule, "provide_automatic_options", False) - and req.method == "OPTIONS" - ): - return self.make_default_options_response() - # otherwise dispatch to the handler for that endpoint - view_args: dict[str, t.Any] = req.view_args # type: ignore[assignment] - return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] - - def full_dispatch_request(self) -> Response: - """Dispatches the request and on top of that performs request - pre and postprocessing as well as HTTP exception catching and - error handling. - - .. versionadded:: 0.7 - """ - self._got_first_request = True - - try: - request_started.send(self, _async_wrapper=self.ensure_sync) - rv = self.preprocess_request() - if rv is None: - rv = self.dispatch_request() - except Exception as e: - rv = self.handle_user_exception(e) - return self.finalize_request(rv) - - def finalize_request( - self, - rv: ft.ResponseReturnValue | HTTPException, - from_error_handler: bool = False, - ) -> Response: - """Given the return value from a view function this finalizes - the request by converting it into a response and invoking the - postprocessing functions. This is invoked for both normal - request dispatching as well as error handlers. - - Because this means that it might be called as a result of a - failure a special safe mode is available which can be enabled - with the `from_error_handler` flag. If enabled, failures in - response processing will be logged and otherwise ignored. - - :internal: - """ - response = self.make_response(rv) - try: - response = self.process_response(response) - request_finished.send( - self, _async_wrapper=self.ensure_sync, response=response - ) - except Exception: - if not from_error_handler: - raise - self.logger.exception( - "Request finalizing failed with an error while handling an error" - ) - return response - - def make_default_options_response(self) -> Response: - """This method is called to create the default ``OPTIONS`` response. - This can be changed through subclassing to change the default - behavior of ``OPTIONS`` responses. - - .. versionadded:: 0.7 - """ - adapter = request_ctx.url_adapter - methods = adapter.allowed_methods() # type: ignore[union-attr] - rv = self.response_class() - rv.allow.update(methods) - return rv - - def ensure_sync(self, func: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: - """Ensure that the function is synchronous for WSGI workers. - Plain ``def`` functions are returned as-is. ``async def`` - functions are wrapped to run and wait for the response. - - Override this method to change how the app runs async views. - - .. versionadded:: 2.0 - """ - if iscoroutinefunction(func): - return self.async_to_sync(func) - - return func - - def async_to_sync( - self, func: t.Callable[..., t.Coroutine[t.Any, t.Any, t.Any]] - ) -> t.Callable[..., t.Any]: - """Return a sync function that will run the coroutine function. - - .. code-block:: python - - result = app.async_to_sync(func)(*args, **kwargs) - - Override this method to change how the app converts async code - to be synchronously callable. - - .. versionadded:: 2.0 - """ - try: - from asgiref.sync import async_to_sync as asgiref_async_to_sync - except ImportError: - raise RuntimeError( - "Install Flask with the 'async' extra in order to use async views." - ) from None - - return asgiref_async_to_sync(func) - - def url_for( - self, - /, - endpoint: str, - *, - _anchor: str | None = None, - _method: str | None = None, - _scheme: str | None = None, - _external: bool | None = None, - **values: t.Any, - ) -> str: - """Generate a URL to the given endpoint with the given values. - - This is called by :func:`flask.url_for`, and can be called - directly as well. - - An *endpoint* is the name of a URL rule, usually added with - :meth:`@app.route() `, and usually the same name as the - view function. A route defined in a :class:`~flask.Blueprint` - will prepend the blueprint's name separated by a ``.`` to the - endpoint. - - In some cases, such as email messages, you want URLs to include - the scheme and domain, like ``https://example.com/hello``. When - not in an active request, URLs will be external by default, but - this requires setting :data:`SERVER_NAME` so Flask knows what - domain to use. :data:`APPLICATION_ROOT` and - :data:`PREFERRED_URL_SCHEME` should also be configured as - needed. This config is only used when not in an active request. - - Functions can be decorated with :meth:`url_defaults` to modify - keyword arguments before the URL is built. - - If building fails for some reason, such as an unknown endpoint - or incorrect values, the app's :meth:`handle_url_build_error` - method is called. If that returns a string, that is returned, - otherwise a :exc:`~werkzeug.routing.BuildError` is raised. - - :param endpoint: The endpoint name associated with the URL to - generate. If this starts with a ``.``, the current blueprint - name (if any) will be used. - :param _anchor: If given, append this as ``#anchor`` to the URL. - :param _method: If given, generate the URL associated with this - method for the endpoint. - :param _scheme: If given, the URL will have this scheme if it - is external. - :param _external: If given, prefer the URL to be internal - (False) or require it to be external (True). External URLs - include the scheme and domain. When not in an active - request, URLs are external by default. - :param values: Values to use for the variable parts of the URL - rule. Unknown keys are appended as query string arguments, - like ``?a=b&c=d``. - - .. versionadded:: 2.2 - Moved from ``flask.url_for``, which calls this method. - """ - req_ctx = _cv_request.get(None) - - if req_ctx is not None: - url_adapter = req_ctx.url_adapter - blueprint_name = req_ctx.request.blueprint - - # If the endpoint starts with "." and the request matches a - # blueprint, the endpoint is relative to the blueprint. - if endpoint[:1] == ".": - if blueprint_name is not None: - endpoint = f"{blueprint_name}{endpoint}" - else: - endpoint = endpoint[1:] - - # When in a request, generate a URL without scheme and - # domain by default, unless a scheme is given. - if _external is None: - _external = _scheme is not None - else: - app_ctx = _cv_app.get(None) - - # If called by helpers.url_for, an app context is active, - # use its url_adapter. Otherwise, app.url_for was called - # directly, build an adapter. - if app_ctx is not None: - url_adapter = app_ctx.url_adapter - else: - url_adapter = self.create_url_adapter(None) - - if url_adapter is None: - raise RuntimeError( - "Unable to build URLs outside an active request" - " without 'SERVER_NAME' configured. Also configure" - " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" - " needed." - ) - - # When outside a request, generate a URL with scheme and - # domain by default. - if _external is None: - _external = True - - # It is an error to set _scheme when _external=False, in order - # to avoid accidental insecure URLs. - if _scheme is not None and not _external: - raise ValueError("When specifying '_scheme', '_external' must be True.") - - self.inject_url_defaults(endpoint, values) - - try: - rv = url_adapter.build( # type: ignore[union-attr] - endpoint, - values, - method=_method, - url_scheme=_scheme, - force_external=_external, - ) - except BuildError as error: - values.update( - _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external - ) - return self.handle_url_build_error(error, endpoint, values) - - if _anchor is not None: - _anchor = _url_quote(_anchor, safe="%!#$&'()*+,/:;=?@") - rv = f"{rv}#{_anchor}" - - return rv - - def make_response(self, rv: ft.ResponseReturnValue) -> Response: - """Convert the return value from a view function to an instance of - :attr:`response_class`. - - :param rv: the return value from the view function. The view function - must return a response. Returning ``None``, or the view ending - without returning, is not allowed. The following types are allowed - for ``view_rv``: - - ``str`` - A response object is created with the string encoded to UTF-8 - as the body. - - ``bytes`` - A response object is created with the bytes as the body. - - ``dict`` - A dictionary that will be jsonify'd before being returned. - - ``list`` - A list that will be jsonify'd before being returned. - - ``generator`` or ``iterator`` - A generator that returns ``str`` or ``bytes`` to be - streamed as the response. - - ``tuple`` - Either ``(body, status, headers)``, ``(body, status)``, or - ``(body, headers)``, where ``body`` is any of the other types - allowed here, ``status`` is a string or an integer, and - ``headers`` is a dictionary or a list of ``(key, value)`` - tuples. If ``body`` is a :attr:`response_class` instance, - ``status`` overwrites the exiting value and ``headers`` are - extended. - - :attr:`response_class` - The object is returned unchanged. - - other :class:`~werkzeug.wrappers.Response` class - The object is coerced to :attr:`response_class`. - - :func:`callable` - The function is called as a WSGI application. The result is - used to create a response object. - - .. versionchanged:: 2.2 - A generator will be converted to a streaming response. - A list will be converted to a JSON response. - - .. versionchanged:: 1.1 - A dict will be converted to a JSON response. - - .. versionchanged:: 0.9 - Previously a tuple was interpreted as the arguments for the - response object. - """ - - status: int | None = None - headers: HeadersValue | None = None - - # unpack tuple returns - if isinstance(rv, tuple): - len_rv = len(rv) - - # a 3-tuple is unpacked directly - if len_rv == 3: - rv, status, headers = rv # type: ignore[misc] - # decide if a 2-tuple has status or headers - elif len_rv == 2: - if isinstance(rv[1], (Headers, dict, tuple, list)): - rv, headers = rv # pyright: ignore - else: - rv, status = rv # type: ignore[assignment,misc] - # other sized tuples are not allowed - else: - raise TypeError( - "The view function did not return a valid response tuple." - " The tuple must have the form (body, status, headers)," - " (body, status), or (body, headers)." - ) - - # the body must not be None - if rv is None: - raise TypeError( - f"The view function for {request.endpoint!r} did not" - " return a valid response. The function either returned" - " None or ended without a return statement." - ) - - # make sure the body is an instance of the response class - if not isinstance(rv, self.response_class): - if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, cabc.Iterator): - # let the response class set the status and headers instead of - # waiting to do it manually, so that the class can handle any - # special logic - rv = self.response_class( - rv, # pyright: ignore - status=status, - headers=headers, # type: ignore[arg-type] - ) - status = headers = None - elif isinstance(rv, (dict, list)): - rv = self.json.response(rv) - elif isinstance(rv, BaseResponse) or callable(rv): - # evaluate a WSGI callable, or coerce a different response - # class to the correct type - try: - rv = self.response_class.force_type( - rv, # type: ignore[arg-type] - request.environ, - ) - except TypeError as e: - raise TypeError( - f"{e}\nThe view function did not return a valid" - " response. The return type must be a string," - " dict, list, tuple with headers or status," - " Response instance, or WSGI callable, but it" - f" was a {type(rv).__name__}." - ).with_traceback(sys.exc_info()[2]) from None - else: - raise TypeError( - "The view function did not return a valid" - " response. The return type must be a string," - " dict, list, tuple with headers or status," - " Response instance, or WSGI callable, but it was a" - f" {type(rv).__name__}." - ) - - rv = t.cast(Response, rv) - # prefer the status if it was provided - if status is not None: - if isinstance(status, (str, bytes, bytearray)): - rv.status = status - else: - rv.status_code = status - - # extend existing headers with provided headers - if headers: - rv.headers.update(headers) - - return rv - - def preprocess_request(self) -> ft.ResponseReturnValue | None: - """Called before the request is dispatched. Calls - :attr:`url_value_preprocessors` registered with the app and the - current blueprint (if any). Then calls :attr:`before_request_funcs` - registered with the app and the blueprint. - - If any :meth:`before_request` handler returns a non-None value, the - value is handled as if it was the return value from the view, and - further request handling is stopped. - """ - names = (None, *reversed(request.blueprints)) - - for name in names: - if name in self.url_value_preprocessors: - for url_func in self.url_value_preprocessors[name]: - url_func(request.endpoint, request.view_args) - - for name in names: - if name in self.before_request_funcs: - for before_func in self.before_request_funcs[name]: - rv = self.ensure_sync(before_func)() - - if rv is not None: - return rv # type: ignore[no-any-return] - - return None - - def process_response(self, response: Response) -> Response: - """Can be overridden in order to modify the response object - before it's sent to the WSGI server. By default this will - call all the :meth:`after_request` decorated functions. - - .. versionchanged:: 0.5 - As of Flask 0.5 the functions registered for after request - execution are called in reverse order of registration. - - :param response: a :attr:`response_class` object. - :return: a new response object or the same, has to be an - instance of :attr:`response_class`. - """ - ctx = request_ctx._get_current_object() # type: ignore[attr-defined] - - for func in ctx._after_request_functions: - response = self.ensure_sync(func)(response) - - for name in chain(request.blueprints, (None,)): - if name in self.after_request_funcs: - for func in reversed(self.after_request_funcs[name]): - response = self.ensure_sync(func)(response) - - if not self.session_interface.is_null_session(ctx.session): - self.session_interface.save_session(self, ctx.session, response) - - return response - - def do_teardown_request( - self, - exc: BaseException | None = _sentinel, # type: ignore[assignment] - ) -> None: - """Called after the request is dispatched and the response is - returned, right before the request context is popped. - - This calls all functions decorated with - :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` - if a blueprint handled the request. Finally, the - :data:`request_tearing_down` signal is sent. - - This is called by - :meth:`RequestContext.pop() `, - which may be delayed during testing to maintain access to - resources. - - :param exc: An unhandled exception raised while dispatching the - request. Detected from the current exception information if - not passed. Passed to each teardown function. - - .. versionchanged:: 0.9 - Added the ``exc`` argument. - """ - if exc is _sentinel: - exc = sys.exc_info()[1] - - for name in chain(request.blueprints, (None,)): - if name in self.teardown_request_funcs: - for func in reversed(self.teardown_request_funcs[name]): - self.ensure_sync(func)(exc) - - request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) - - def do_teardown_appcontext( - self, - exc: BaseException | None = _sentinel, # type: ignore[assignment] - ) -> None: - """Called right before the application context is popped. - - When handling a request, the application context is popped - after the request context. See :meth:`do_teardown_request`. - - This calls all functions decorated with - :meth:`teardown_appcontext`. Then the - :data:`appcontext_tearing_down` signal is sent. - - This is called by - :meth:`AppContext.pop() `. - - .. versionadded:: 0.9 - """ - if exc is _sentinel: - exc = sys.exc_info()[1] - - for func in reversed(self.teardown_appcontext_funcs): - self.ensure_sync(func)(exc) - - appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) - - def app_context(self) -> AppContext: - """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` - block to push the context, which will make :data:`current_app` - point at this application. - - An application context is automatically pushed by - :meth:`RequestContext.push() ` - when handling a request, and when running a CLI command. Use - this to manually create a context outside of these situations. - - :: - - with app.app_context(): - init_db() - - See :doc:`/appcontext`. - - .. versionadded:: 0.9 - """ - return AppContext(self) - - def request_context(self, environ: WSGIEnvironment) -> RequestContext: - """Create a :class:`~flask.ctx.RequestContext` representing a - WSGI environment. Use a ``with`` block to push the context, - which will make :data:`request` point at this request. - - See :doc:`/reqcontext`. - - Typically you should not call this from your own code. A request - context is automatically pushed by the :meth:`wsgi_app` when - handling a request. Use :meth:`test_request_context` to create - an environment and context instead of this method. - - :param environ: a WSGI environment - """ - return RequestContext(self, environ) - - def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext: - """Create a :class:`~flask.ctx.RequestContext` for a WSGI - environment created from the given values. This is mostly useful - during testing, where you may want to run a function that uses - request data without dispatching a full request. - - See :doc:`/reqcontext`. - - Use a ``with`` block to push the context, which will make - :data:`request` point at the request for the created - environment. :: - - with app.test_request_context(...): - generate_report() - - When using the shell, it may be easier to push and pop the - context manually to avoid indentation. :: - - ctx = app.test_request_context(...) - ctx.push() - ... - ctx.pop() - - Takes the same arguments as Werkzeug's - :class:`~werkzeug.test.EnvironBuilder`, with some defaults from - the application. See the linked Werkzeug docs for most of the - available arguments. Flask-specific behavior is listed here. - - :param path: URL path being requested. - :param base_url: Base URL where the app is being served, which - ``path`` is relative to. If not given, built from - :data:`PREFERRED_URL_SCHEME`, ``subdomain``, - :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. - :param subdomain: Subdomain name to append to - :data:`SERVER_NAME`. - :param url_scheme: Scheme to use instead of - :data:`PREFERRED_URL_SCHEME`. - :param data: The request body, either as a string or a dict of - form keys and values. - :param json: If given, this is serialized as JSON and passed as - ``data``. Also defaults ``content_type`` to - ``application/json``. - :param args: other positional arguments passed to - :class:`~werkzeug.test.EnvironBuilder`. - :param kwargs: other keyword arguments passed to - :class:`~werkzeug.test.EnvironBuilder`. - """ - from .testing import EnvironBuilder - - builder = EnvironBuilder(self, *args, **kwargs) - - try: - return self.request_context(builder.get_environ()) - finally: - builder.close() - - def wsgi_app( - self, environ: WSGIEnvironment, start_response: StartResponse - ) -> cabc.Iterable[bytes]: - """The actual WSGI application. This is not implemented in - :meth:`__call__` so that middlewares can be applied without - losing a reference to the app object. Instead of doing this:: - - app = MyMiddleware(app) - - It's a better idea to do this instead:: - - app.wsgi_app = MyMiddleware(app.wsgi_app) - - Then you still have the original application object around and - can continue to call methods on it. - - .. versionchanged:: 0.7 - Teardown events for the request and app contexts are called - even if an unhandled error occurs. Other events may not be - called depending on when an error occurs during dispatch. - See :ref:`callbacks-and-errors`. - - :param environ: A WSGI environment. - :param start_response: A callable accepting a status code, - a list of headers, and an optional exception context to - start the response. - """ - ctx = self.request_context(environ) - error: BaseException | None = None - try: - try: - ctx.push() - response = self.full_dispatch_request() - except Exception as e: - error = e - response = self.handle_exception(e) - except: # noqa: B001 - error = sys.exc_info()[1] - raise - return response(environ, start_response) - finally: - if "werkzeug.debug.preserve_context" in environ: - environ["werkzeug.debug.preserve_context"](_cv_app.get()) - environ["werkzeug.debug.preserve_context"](_cv_request.get()) - - if error is not None and self.should_ignore_error(error): - error = None - - ctx.pop(error) - - def __call__( - self, environ: WSGIEnvironment, start_response: StartResponse - ) -> cabc.Iterable[bytes]: - """The WSGI server calls the Flask application object as the - WSGI application. This calls :meth:`wsgi_app`, which can be - wrapped to apply middleware. - """ - return self.wsgi_app(environ, start_response) diff --git a/serverenv/lib/python3.9/site-packages/flask/blueprints.py b/serverenv/lib/python3.9/site-packages/flask/blueprints.py deleted file mode 100644 index b6d4e43..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/blueprints.py +++ /dev/null @@ -1,128 +0,0 @@ -from __future__ import annotations - -import os -import typing as t -from datetime import timedelta - -from .cli import AppGroup -from .globals import current_app -from .helpers import send_from_directory -from .sansio.blueprints import Blueprint as SansioBlueprint -from .sansio.blueprints import BlueprintSetupState as BlueprintSetupState # noqa -from .sansio.scaffold import _sentinel - -if t.TYPE_CHECKING: # pragma: no cover - from .wrappers import Response - - -class Blueprint(SansioBlueprint): - def __init__( - self, - name: str, - import_name: str, - static_folder: str | os.PathLike[str] | None = None, - static_url_path: str | None = None, - template_folder: str | os.PathLike[str] | None = None, - url_prefix: str | None = None, - subdomain: str | None = None, - url_defaults: dict[str, t.Any] | None = None, - root_path: str | None = None, - cli_group: str | None = _sentinel, # type: ignore - ) -> None: - super().__init__( - name, - import_name, - static_folder, - static_url_path, - template_folder, - url_prefix, - subdomain, - url_defaults, - root_path, - cli_group, - ) - - #: The Click command group for registering CLI commands for this - #: object. The commands are available from the ``flask`` command - #: once the application has been discovered and blueprints have - #: been registered. - self.cli = AppGroup() - - # Set the name of the Click group in case someone wants to add - # the app's commands to another CLI tool. - self.cli.name = self.name - - def get_send_file_max_age(self, filename: str | None) -> int | None: - """Used by :func:`send_file` to determine the ``max_age`` cache - value for a given file path if it wasn't passed. - - By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from - the configuration of :data:`~flask.current_app`. This defaults - to ``None``, which tells the browser to use conditional requests - instead of a timed cache, which is usually preferable. - - Note this is a duplicate of the same method in the Flask - class. - - .. versionchanged:: 2.0 - The default configuration is ``None`` instead of 12 hours. - - .. versionadded:: 0.9 - """ - value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] - - if value is None: - return None - - if isinstance(value, timedelta): - return int(value.total_seconds()) - - return value # type: ignore[no-any-return] - - def send_static_file(self, filename: str) -> Response: - """The view function used to serve files from - :attr:`static_folder`. A route is automatically registered for - this view at :attr:`static_url_path` if :attr:`static_folder` is - set. - - Note this is a duplicate of the same method in the Flask - class. - - .. versionadded:: 0.5 - - """ - if not self.has_static_folder: - raise RuntimeError("'static_folder' must be set to serve static_files.") - - # send_file only knows to call get_send_file_max_age on the app, - # call it here so it works for blueprints too. - max_age = self.get_send_file_max_age(filename) - return send_from_directory( - t.cast(str, self.static_folder), filename, max_age=max_age - ) - - def open_resource( - self, resource: str, mode: str = "rb", encoding: str | None = "utf-8" - ) -> t.IO[t.AnyStr]: - """Open a resource file relative to :attr:`root_path` for reading. The - blueprint-relative equivalent of the app's :meth:`~.Flask.open_resource` - method. - - :param resource: Path to the resource relative to :attr:`root_path`. - :param mode: Open the file in this mode. Only reading is supported, - valid values are ``"r"`` (or ``"rt"``) and ``"rb"``. - :param encoding: Open the file with this encoding when opening in text - mode. This is ignored when opening in binary mode. - - .. versionchanged:: 3.1 - Added the ``encoding`` parameter. - """ - if mode not in {"r", "rt", "rb"}: - raise ValueError("Resources can only be opened for reading.") - - path = os.path.join(self.root_path, resource) - - if mode == "rb": - return open(path, mode) # pyright: ignore - - return open(path, mode, encoding=encoding) diff --git a/serverenv/lib/python3.9/site-packages/flask/cli.py b/serverenv/lib/python3.9/site-packages/flask/cli.py deleted file mode 100644 index ed11f25..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/cli.py +++ /dev/null @@ -1,1135 +0,0 @@ -from __future__ import annotations - -import ast -import collections.abc as cabc -import importlib.metadata -import inspect -import os -import platform -import re -import sys -import traceback -import typing as t -from functools import update_wrapper -from operator import itemgetter -from types import ModuleType - -import click -from click.core import ParameterSource -from werkzeug import run_simple -from werkzeug.serving import is_running_from_reloader -from werkzeug.utils import import_string - -from .globals import current_app -from .helpers import get_debug_flag -from .helpers import get_load_dotenv - -if t.TYPE_CHECKING: - import ssl - - from _typeshed.wsgi import StartResponse - from _typeshed.wsgi import WSGIApplication - from _typeshed.wsgi import WSGIEnvironment - - from .app import Flask - - -class NoAppException(click.UsageError): - """Raised if an application cannot be found or loaded.""" - - -def find_best_app(module: ModuleType) -> Flask: - """Given a module instance this tries to find the best possible - application in the module or raises an exception. - """ - from . import Flask - - # Search for the most common names first. - for attr_name in ("app", "application"): - app = getattr(module, attr_name, None) - - if isinstance(app, Flask): - return app - - # Otherwise find the only object that is a Flask instance. - matches = [v for v in module.__dict__.values() if isinstance(v, Flask)] - - if len(matches) == 1: - return matches[0] - elif len(matches) > 1: - raise NoAppException( - "Detected multiple Flask applications in module" - f" '{module.__name__}'. Use '{module.__name__}:name'" - " to specify the correct one." - ) - - # Search for app factory functions. - for attr_name in ("create_app", "make_app"): - app_factory = getattr(module, attr_name, None) - - if inspect.isfunction(app_factory): - try: - app = app_factory() - - if isinstance(app, Flask): - return app - except TypeError as e: - if not _called_with_wrong_args(app_factory): - raise - - raise NoAppException( - f"Detected factory '{attr_name}' in module '{module.__name__}'," - " but could not call it without arguments. Use" - f" '{module.__name__}:{attr_name}(args)'" - " to specify arguments." - ) from e - - raise NoAppException( - "Failed to find Flask application or factory in module" - f" '{module.__name__}'. Use '{module.__name__}:name'" - " to specify one." - ) - - -def _called_with_wrong_args(f: t.Callable[..., Flask]) -> bool: - """Check whether calling a function raised a ``TypeError`` because - the call failed or because something in the factory raised the - error. - - :param f: The function that was called. - :return: ``True`` if the call failed. - """ - tb = sys.exc_info()[2] - - try: - while tb is not None: - if tb.tb_frame.f_code is f.__code__: - # In the function, it was called successfully. - return False - - tb = tb.tb_next - - # Didn't reach the function. - return True - finally: - # Delete tb to break a circular reference. - # https://docs.python.org/2/library/sys.html#sys.exc_info - del tb - - -def find_app_by_string(module: ModuleType, app_name: str) -> Flask: - """Check if the given string is a variable name or a function. Call - a function to get the app instance, or return the variable directly. - """ - from . import Flask - - # Parse app_name as a single expression to determine if it's a valid - # attribute name or function call. - try: - expr = ast.parse(app_name.strip(), mode="eval").body - except SyntaxError: - raise NoAppException( - f"Failed to parse {app_name!r} as an attribute name or function call." - ) from None - - if isinstance(expr, ast.Name): - name = expr.id - args = [] - kwargs = {} - elif isinstance(expr, ast.Call): - # Ensure the function name is an attribute name only. - if not isinstance(expr.func, ast.Name): - raise NoAppException( - f"Function reference must be a simple name: {app_name!r}." - ) - - name = expr.func.id - - # Parse the positional and keyword arguments as literals. - try: - args = [ast.literal_eval(arg) for arg in expr.args] - kwargs = { - kw.arg: ast.literal_eval(kw.value) - for kw in expr.keywords - if kw.arg is not None - } - except ValueError: - # literal_eval gives cryptic error messages, show a generic - # message with the full expression instead. - raise NoAppException( - f"Failed to parse arguments as literal values: {app_name!r}." - ) from None - else: - raise NoAppException( - f"Failed to parse {app_name!r} as an attribute name or function call." - ) - - try: - attr = getattr(module, name) - except AttributeError as e: - raise NoAppException( - f"Failed to find attribute {name!r} in {module.__name__!r}." - ) from e - - # If the attribute is a function, call it with any args and kwargs - # to get the real application. - if inspect.isfunction(attr): - try: - app = attr(*args, **kwargs) - except TypeError as e: - if not _called_with_wrong_args(attr): - raise - - raise NoAppException( - f"The factory {app_name!r} in module" - f" {module.__name__!r} could not be called with the" - " specified arguments." - ) from e - else: - app = attr - - if isinstance(app, Flask): - return app - - raise NoAppException( - "A valid Flask application was not obtained from" - f" '{module.__name__}:{app_name}'." - ) - - -def prepare_import(path: str) -> str: - """Given a filename this will try to calculate the python path, add it - to the search path and return the actual module name that is expected. - """ - path = os.path.realpath(path) - - fname, ext = os.path.splitext(path) - if ext == ".py": - path = fname - - if os.path.basename(path) == "__init__": - path = os.path.dirname(path) - - module_name = [] - - # move up until outside package structure (no __init__.py) - while True: - path, name = os.path.split(path) - module_name.append(name) - - if not os.path.exists(os.path.join(path, "__init__.py")): - break - - if sys.path[0] != path: - sys.path.insert(0, path) - - return ".".join(module_name[::-1]) - - -@t.overload -def locate_app( - module_name: str, app_name: str | None, raise_if_not_found: t.Literal[True] = True -) -> Flask: ... - - -@t.overload -def locate_app( - module_name: str, app_name: str | None, raise_if_not_found: t.Literal[False] = ... -) -> Flask | None: ... - - -def locate_app( - module_name: str, app_name: str | None, raise_if_not_found: bool = True -) -> Flask | None: - try: - __import__(module_name) - except ImportError: - # Reraise the ImportError if it occurred within the imported module. - # Determine this by checking whether the trace has a depth > 1. - if sys.exc_info()[2].tb_next: # type: ignore[union-attr] - raise NoAppException( - f"While importing {module_name!r}, an ImportError was" - f" raised:\n\n{traceback.format_exc()}" - ) from None - elif raise_if_not_found: - raise NoAppException(f"Could not import {module_name!r}.") from None - else: - return None - - module = sys.modules[module_name] - - if app_name is None: - return find_best_app(module) - else: - return find_app_by_string(module, app_name) - - -def get_version(ctx: click.Context, param: click.Parameter, value: t.Any) -> None: - if not value or ctx.resilient_parsing: - return - - flask_version = importlib.metadata.version("flask") - werkzeug_version = importlib.metadata.version("werkzeug") - - click.echo( - f"Python {platform.python_version()}\n" - f"Flask {flask_version}\n" - f"Werkzeug {werkzeug_version}", - color=ctx.color, - ) - ctx.exit() - - -version_option = click.Option( - ["--version"], - help="Show the Flask version.", - expose_value=False, - callback=get_version, - is_flag=True, - is_eager=True, -) - - -class ScriptInfo: - """Helper object to deal with Flask applications. This is usually not - necessary to interface with as it's used internally in the dispatching - to click. In future versions of Flask this object will most likely play - a bigger role. Typically it's created automatically by the - :class:`FlaskGroup` but you can also manually create it and pass it - onwards as click object. - - .. versionchanged:: 3.1 - Added the ``load_dotenv_defaults`` parameter and attribute. - """ - - def __init__( - self, - app_import_path: str | None = None, - create_app: t.Callable[..., Flask] | None = None, - set_debug_flag: bool = True, - load_dotenv_defaults: bool = True, - ) -> None: - #: Optionally the import path for the Flask application. - self.app_import_path = app_import_path - #: Optionally a function that is passed the script info to create - #: the instance of the application. - self.create_app = create_app - #: A dictionary with arbitrary data that can be associated with - #: this script info. - self.data: dict[t.Any, t.Any] = {} - self.set_debug_flag = set_debug_flag - - self.load_dotenv_defaults = get_load_dotenv(load_dotenv_defaults) - """Whether default ``.flaskenv`` and ``.env`` files should be loaded. - - ``ScriptInfo`` doesn't load anything, this is for reference when doing - the load elsewhere during processing. - - .. versionadded:: 3.1 - """ - - self._loaded_app: Flask | None = None - - def load_app(self) -> Flask: - """Loads the Flask app (if not yet loaded) and returns it. Calling - this multiple times will just result in the already loaded app to - be returned. - """ - if self._loaded_app is not None: - return self._loaded_app - app: Flask | None = None - if self.create_app is not None: - app = self.create_app() - else: - if self.app_import_path: - path, name = ( - re.split(r":(?![\\/])", self.app_import_path, maxsplit=1) + [None] - )[:2] - import_name = prepare_import(path) - app = locate_app(import_name, name) - else: - for path in ("wsgi.py", "app.py"): - import_name = prepare_import(path) - app = locate_app(import_name, None, raise_if_not_found=False) - - if app is not None: - break - - if app is None: - raise NoAppException( - "Could not locate a Flask application. Use the" - " 'flask --app' option, 'FLASK_APP' environment" - " variable, or a 'wsgi.py' or 'app.py' file in the" - " current directory." - ) - - if self.set_debug_flag: - # Update the app's debug flag through the descriptor so that - # other values repopulate as well. - app.debug = get_debug_flag() - - self._loaded_app = app - return app - - -pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) - - -def with_appcontext(f: F) -> F: - """Wraps a callback so that it's guaranteed to be executed with the - script's application context. - - Custom commands (and their options) registered under ``app.cli`` or - ``blueprint.cli`` will always have an app context available, this - decorator is not required in that case. - - .. versionchanged:: 2.2 - The app context is active for subcommands as well as the - decorated callback. The app context is always available to - ``app.cli`` command and parameter callbacks. - """ - - @click.pass_context - def decorator(ctx: click.Context, /, *args: t.Any, **kwargs: t.Any) -> t.Any: - if not current_app: - app = ctx.ensure_object(ScriptInfo).load_app() - ctx.with_resource(app.app_context()) - - return ctx.invoke(f, *args, **kwargs) - - return update_wrapper(decorator, f) # type: ignore[return-value] - - -class AppGroup(click.Group): - """This works similar to a regular click :class:`~click.Group` but it - changes the behavior of the :meth:`command` decorator so that it - automatically wraps the functions in :func:`with_appcontext`. - - Not to be confused with :class:`FlaskGroup`. - """ - - def command( # type: ignore[override] - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], click.Command]: - """This works exactly like the method of the same name on a regular - :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` - unless it's disabled by passing ``with_appcontext=False``. - """ - wrap_for_ctx = kwargs.pop("with_appcontext", True) - - def decorator(f: t.Callable[..., t.Any]) -> click.Command: - if wrap_for_ctx: - f = with_appcontext(f) - return super(AppGroup, self).command(*args, **kwargs)(f) # type: ignore[no-any-return] - - return decorator - - def group( # type: ignore[override] - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], click.Group]: - """This works exactly like the method of the same name on a regular - :class:`click.Group` but it defaults the group class to - :class:`AppGroup`. - """ - kwargs.setdefault("cls", AppGroup) - return super().group(*args, **kwargs) # type: ignore[no-any-return] - - -def _set_app(ctx: click.Context, param: click.Option, value: str | None) -> str | None: - if value is None: - return None - - info = ctx.ensure_object(ScriptInfo) - info.app_import_path = value - return value - - -# This option is eager so the app will be available if --help is given. -# --help is also eager, so --app must be before it in the param list. -# no_args_is_help bypasses eager processing, so this option must be -# processed manually in that case to ensure FLASK_APP gets picked up. -_app_option = click.Option( - ["-A", "--app"], - metavar="IMPORT", - help=( - "The Flask application or factory function to load, in the form 'module:name'." - " Module can be a dotted import or file path. Name is not required if it is" - " 'app', 'application', 'create_app', or 'make_app', and can be 'name(args)' to" - " pass arguments." - ), - is_eager=True, - expose_value=False, - callback=_set_app, -) - - -def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> bool | None: - # If the flag isn't provided, it will default to False. Don't use - # that, let debug be set by env in that case. - source = ctx.get_parameter_source(param.name) # type: ignore[arg-type] - - if source is not None and source in ( - ParameterSource.DEFAULT, - ParameterSource.DEFAULT_MAP, - ): - return None - - # Set with env var instead of ScriptInfo.load so that it can be - # accessed early during a factory function. - os.environ["FLASK_DEBUG"] = "1" if value else "0" - return value - - -_debug_option = click.Option( - ["--debug/--no-debug"], - help="Set debug mode.", - expose_value=False, - callback=_set_debug, -) - - -def _env_file_callback( - ctx: click.Context, param: click.Option, value: str | None -) -> str | None: - try: - import dotenv # noqa: F401 - except ImportError: - # Only show an error if a value was passed, otherwise we still want to - # call load_dotenv and show a message without exiting. - if value is not None: - raise click.BadParameter( - "python-dotenv must be installed to load an env file.", - ctx=ctx, - param=param, - ) from None - - # Load if a value was passed, or we want to load default files, or both. - if value is not None or ctx.obj.load_dotenv_defaults: - load_dotenv(value, load_defaults=ctx.obj.load_dotenv_defaults) - - return value - - -# This option is eager so env vars are loaded as early as possible to be -# used by other options. -_env_file_option = click.Option( - ["-e", "--env-file"], - type=click.Path(exists=True, dir_okay=False), - help=( - "Load environment variables from this file, taking precedence over" - " those set by '.env' and '.flaskenv'. Variables set directly in the" - " environment take highest precedence. python-dotenv must be installed." - ), - is_eager=True, - expose_value=False, - callback=_env_file_callback, -) - - -class FlaskGroup(AppGroup): - """Special subclass of the :class:`AppGroup` group that supports - loading more commands from the configured Flask app. Normally a - developer does not have to interface with this class but there are - some very advanced use cases for which it makes sense to create an - instance of this. see :ref:`custom-scripts`. - - :param add_default_commands: if this is True then the default run and - shell commands will be added. - :param add_version_option: adds the ``--version`` option. - :param create_app: an optional callback that is passed the script info and - returns the loaded app. - :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` - files to set environment variables. Will also change the working - directory to the directory containing the first file found. - :param set_debug_flag: Set the app's debug flag. - - .. versionchanged:: 3.1 - ``-e path`` takes precedence over default ``.env`` and ``.flaskenv`` files. - - .. versionchanged:: 2.2 - Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options. - - .. versionchanged:: 2.2 - An app context is pushed when running ``app.cli`` commands, so - ``@with_appcontext`` is no longer required for those commands. - - .. versionchanged:: 1.0 - If installed, python-dotenv will be used to load environment variables - from :file:`.env` and :file:`.flaskenv` files. - """ - - def __init__( - self, - add_default_commands: bool = True, - create_app: t.Callable[..., Flask] | None = None, - add_version_option: bool = True, - load_dotenv: bool = True, - set_debug_flag: bool = True, - **extra: t.Any, - ) -> None: - params: list[click.Parameter] = list(extra.pop("params", None) or ()) - # Processing is done with option callbacks instead of a group - # callback. This allows users to make a custom group callback - # without losing the behavior. --env-file must come first so - # that it is eagerly evaluated before --app. - params.extend((_env_file_option, _app_option, _debug_option)) - - if add_version_option: - params.append(version_option) - - if "context_settings" not in extra: - extra["context_settings"] = {} - - extra["context_settings"].setdefault("auto_envvar_prefix", "FLASK") - - super().__init__(params=params, **extra) - - self.create_app = create_app - self.load_dotenv = load_dotenv - self.set_debug_flag = set_debug_flag - - if add_default_commands: - self.add_command(run_command) - self.add_command(shell_command) - self.add_command(routes_command) - - self._loaded_plugin_commands = False - - def _load_plugin_commands(self) -> None: - if self._loaded_plugin_commands: - return - - if sys.version_info >= (3, 10): - from importlib import metadata - else: - # Use a backport on Python < 3.10. We technically have - # importlib.metadata on 3.8+, but the API changed in 3.10, - # so use the backport for consistency. - import importlib_metadata as metadata # pyright: ignore - - for ep in metadata.entry_points(group="flask.commands"): - self.add_command(ep.load(), ep.name) - - self._loaded_plugin_commands = True - - def get_command(self, ctx: click.Context, name: str) -> click.Command | None: - self._load_plugin_commands() - # Look up built-in and plugin commands, which should be - # available even if the app fails to load. - rv = super().get_command(ctx, name) - - if rv is not None: - return rv - - info = ctx.ensure_object(ScriptInfo) - - # Look up commands provided by the app, showing an error and - # continuing if the app couldn't be loaded. - try: - app = info.load_app() - except NoAppException as e: - click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") - return None - - # Push an app context for the loaded app unless it is already - # active somehow. This makes the context available to parameter - # and command callbacks without needing @with_appcontext. - if not current_app or current_app._get_current_object() is not app: # type: ignore[attr-defined] - ctx.with_resource(app.app_context()) - - return app.cli.get_command(ctx, name) - - def list_commands(self, ctx: click.Context) -> list[str]: - self._load_plugin_commands() - # Start with the built-in and plugin commands. - rv = set(super().list_commands(ctx)) - info = ctx.ensure_object(ScriptInfo) - - # Add commands provided by the app, showing an error and - # continuing if the app couldn't be loaded. - try: - rv.update(info.load_app().cli.list_commands(ctx)) - except NoAppException as e: - # When an app couldn't be loaded, show the error message - # without the traceback. - click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") - except Exception: - # When any other errors occurred during loading, show the - # full traceback. - click.secho(f"{traceback.format_exc()}\n", err=True, fg="red") - - return sorted(rv) - - def make_context( - self, - info_name: str | None, - args: list[str], - parent: click.Context | None = None, - **extra: t.Any, - ) -> click.Context: - # Set a flag to tell app.run to become a no-op. If app.run was - # not in a __name__ == __main__ guard, it would start the server - # when importing, blocking whatever command is being called. - os.environ["FLASK_RUN_FROM_CLI"] = "true" - - if "obj" not in extra and "obj" not in self.context_settings: - extra["obj"] = ScriptInfo( - create_app=self.create_app, - set_debug_flag=self.set_debug_flag, - load_dotenv_defaults=self.load_dotenv, - ) - - return super().make_context(info_name, args, parent=parent, **extra) - - def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: - if (not args and self.no_args_is_help) or ( - len(args) == 1 and args[0] in self.get_help_option_names(ctx) - ): - # Attempt to load --env-file and --app early in case they - # were given as env vars. Otherwise no_args_is_help will not - # see commands from app.cli. - _env_file_option.handle_parse_result(ctx, {}, []) - _app_option.handle_parse_result(ctx, {}, []) - - return super().parse_args(ctx, args) - - -def _path_is_ancestor(path: str, other: str) -> bool: - """Take ``other`` and remove the length of ``path`` from it. Then join it - to ``path``. If it is the original value, ``path`` is an ancestor of - ``other``.""" - return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other - - -def load_dotenv( - path: str | os.PathLike[str] | None = None, load_defaults: bool = True -) -> bool: - """Load "dotenv" files to set environment variables. A given path takes - precedence over ``.env``, which takes precedence over ``.flaskenv``. After - loading and combining these files, values are only set if the key is not - already set in ``os.environ``. - - This is a no-op if `python-dotenv`_ is not installed. - - .. _python-dotenv: https://github.com/theskumar/python-dotenv#readme - - :param path: Load the file at this location. - :param load_defaults: Search for and load the default ``.flaskenv`` and - ``.env`` files. - :return: ``True`` if at least one env var was loaded. - - .. versionchanged:: 3.1 - Added the ``load_defaults`` parameter. A given path takes precedence - over default files. - - .. versionchanged:: 2.0 - The current directory is not changed to the location of the - loaded file. - - .. versionchanged:: 2.0 - When loading the env files, set the default encoding to UTF-8. - - .. versionchanged:: 1.1.0 - Returns ``False`` when python-dotenv is not installed, or when - the given path isn't a file. - - .. versionadded:: 1.0 - """ - try: - import dotenv - except ImportError: - if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"): - click.secho( - " * Tip: There are .env files present. Install python-dotenv" - " to use them.", - fg="yellow", - err=True, - ) - - return False - - data: dict[str, str | None] = {} - - if load_defaults: - for default_name in (".flaskenv", ".env"): - if not (default_path := dotenv.find_dotenv(default_name, usecwd=True)): - continue - - data |= dotenv.dotenv_values(default_path, encoding="utf-8") - - if path is not None and os.path.isfile(path): - data |= dotenv.dotenv_values(path, encoding="utf-8") - - for key, value in data.items(): - if key in os.environ or value is None: - continue - - os.environ[key] = value - - return bool(data) # True if at least one env var was loaded. - - -def show_server_banner(debug: bool, app_import_path: str | None) -> None: - """Show extra startup messages the first time the server is run, - ignoring the reloader. - """ - if is_running_from_reloader(): - return - - if app_import_path is not None: - click.echo(f" * Serving Flask app '{app_import_path}'") - - if debug is not None: - click.echo(f" * Debug mode: {'on' if debug else 'off'}") - - -class CertParamType(click.ParamType): - """Click option type for the ``--cert`` option. Allows either an - existing file, the string ``'adhoc'``, or an import for a - :class:`~ssl.SSLContext` object. - """ - - name = "path" - - def __init__(self) -> None: - self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True) - - def convert( - self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None - ) -> t.Any: - try: - import ssl - except ImportError: - raise click.BadParameter( - 'Using "--cert" requires Python to be compiled with SSL support.', - ctx, - param, - ) from None - - try: - return self.path_type(value, param, ctx) - except click.BadParameter: - value = click.STRING(value, param, ctx).lower() - - if value == "adhoc": - try: - import cryptography # noqa: F401 - except ImportError: - raise click.BadParameter( - "Using ad-hoc certificates requires the cryptography library.", - ctx, - param, - ) from None - - return value - - obj = import_string(value, silent=True) - - if isinstance(obj, ssl.SSLContext): - return obj - - raise - - -def _validate_key(ctx: click.Context, param: click.Parameter, value: t.Any) -> t.Any: - """The ``--key`` option must be specified when ``--cert`` is a file. - Modifies the ``cert`` param to be a ``(cert, key)`` pair if needed. - """ - cert = ctx.params.get("cert") - is_adhoc = cert == "adhoc" - - try: - import ssl - except ImportError: - is_context = False - else: - is_context = isinstance(cert, ssl.SSLContext) - - if value is not None: - if is_adhoc: - raise click.BadParameter( - 'When "--cert" is "adhoc", "--key" is not used.', ctx, param - ) - - if is_context: - raise click.BadParameter( - 'When "--cert" is an SSLContext object, "--key" is not used.', - ctx, - param, - ) - - if not cert: - raise click.BadParameter('"--cert" must also be specified.', ctx, param) - - ctx.params["cert"] = cert, value - - else: - if cert and not (is_adhoc or is_context): - raise click.BadParameter('Required when using "--cert".', ctx, param) - - return value - - -class SeparatedPathType(click.Path): - """Click option type that accepts a list of values separated by the - OS's path separator (``:``, ``;`` on Windows). Each value is - validated as a :class:`click.Path` type. - """ - - def convert( - self, value: t.Any, param: click.Parameter | None, ctx: click.Context | None - ) -> t.Any: - items = self.split_envvar_value(value) - # can't call no-arg super() inside list comprehension until Python 3.12 - super_convert = super().convert - return [super_convert(item, param, ctx) for item in items] - - -@click.command("run", short_help="Run a development server.") -@click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.") -@click.option("--port", "-p", default=5000, help="The port to bind to.") -@click.option( - "--cert", - type=CertParamType(), - help="Specify a certificate file to use HTTPS.", - is_eager=True, -) -@click.option( - "--key", - type=click.Path(exists=True, dir_okay=False, resolve_path=True), - callback=_validate_key, - expose_value=False, - help="The key file to use when specifying a certificate.", -) -@click.option( - "--reload/--no-reload", - default=None, - help="Enable or disable the reloader. By default the reloader " - "is active if debug is enabled.", -) -@click.option( - "--debugger/--no-debugger", - default=None, - help="Enable or disable the debugger. By default the debugger " - "is active if debug is enabled.", -) -@click.option( - "--with-threads/--without-threads", - default=True, - help="Enable or disable multithreading.", -) -@click.option( - "--extra-files", - default=None, - type=SeparatedPathType(), - help=( - "Extra files that trigger a reload on change. Multiple paths" - f" are separated by {os.path.pathsep!r}." - ), -) -@click.option( - "--exclude-patterns", - default=None, - type=SeparatedPathType(), - help=( - "Files matching these fnmatch patterns will not trigger a reload" - " on change. Multiple patterns are separated by" - f" {os.path.pathsep!r}." - ), -) -@pass_script_info -def run_command( - info: ScriptInfo, - host: str, - port: int, - reload: bool, - debugger: bool, - with_threads: bool, - cert: ssl.SSLContext | tuple[str, str | None] | t.Literal["adhoc"] | None, - extra_files: list[str] | None, - exclude_patterns: list[str] | None, -) -> None: - """Run a local development server. - - This server is for development purposes only. It does not provide - the stability, security, or performance of production WSGI servers. - - The reloader and debugger are enabled by default with the '--debug' - option. - """ - try: - app: WSGIApplication = info.load_app() # pyright: ignore - except Exception as e: - if is_running_from_reloader(): - # When reloading, print out the error immediately, but raise - # it later so the debugger or server can handle it. - traceback.print_exc() - err = e - - def app( - environ: WSGIEnvironment, start_response: StartResponse - ) -> cabc.Iterable[bytes]: - raise err from None - - else: - # When not reloading, raise the error immediately so the - # command fails. - raise e from None - - debug = get_debug_flag() - - if reload is None: - reload = debug - - if debugger is None: - debugger = debug - - show_server_banner(debug, info.app_import_path) - - run_simple( - host, - port, - app, - use_reloader=reload, - use_debugger=debugger, - threaded=with_threads, - ssl_context=cert, - extra_files=extra_files, - exclude_patterns=exclude_patterns, - ) - - -run_command.params.insert(0, _debug_option) - - -@click.command("shell", short_help="Run a shell in the app context.") -@with_appcontext -def shell_command() -> None: - """Run an interactive Python shell in the context of a given - Flask application. The application will populate the default - namespace of this shell according to its configuration. - - This is useful for executing small snippets of management code - without having to manually configure the application. - """ - import code - - banner = ( - f"Python {sys.version} on {sys.platform}\n" - f"App: {current_app.import_name}\n" - f"Instance: {current_app.instance_path}" - ) - ctx: dict[str, t.Any] = {} - - # Support the regular Python interpreter startup script if someone - # is using it. - startup = os.environ.get("PYTHONSTARTUP") - if startup and os.path.isfile(startup): - with open(startup) as f: - eval(compile(f.read(), startup, "exec"), ctx) - - ctx.update(current_app.make_shell_context()) - - # Site, customize, or startup script can set a hook to call when - # entering interactive mode. The default one sets up readline with - # tab and history completion. - interactive_hook = getattr(sys, "__interactivehook__", None) - - if interactive_hook is not None: - try: - import readline - from rlcompleter import Completer - except ImportError: - pass - else: - # rlcompleter uses __main__.__dict__ by default, which is - # flask.__main__. Use the shell context instead. - readline.set_completer(Completer(ctx).complete) - - interactive_hook() - - code.interact(banner=banner, local=ctx) - - -@click.command("routes", short_help="Show the routes for the app.") -@click.option( - "--sort", - "-s", - type=click.Choice(("endpoint", "methods", "domain", "rule", "match")), - default="endpoint", - help=( - "Method to sort routes by. 'match' is the order that Flask will match routes" - " when dispatching a request." - ), -) -@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.") -@with_appcontext -def routes_command(sort: str, all_methods: bool) -> None: - """Show all registered routes with endpoints and methods.""" - rules = list(current_app.url_map.iter_rules()) - - if not rules: - click.echo("No routes were registered.") - return - - ignored_methods = set() if all_methods else {"HEAD", "OPTIONS"} - host_matching = current_app.url_map.host_matching - has_domain = any(rule.host if host_matching else rule.subdomain for rule in rules) - rows = [] - - for rule in rules: - row = [ - rule.endpoint, - ", ".join(sorted((rule.methods or set()) - ignored_methods)), - ] - - if has_domain: - row.append((rule.host if host_matching else rule.subdomain) or "") - - row.append(rule.rule) - rows.append(row) - - headers = ["Endpoint", "Methods"] - sorts = ["endpoint", "methods"] - - if has_domain: - headers.append("Host" if host_matching else "Subdomain") - sorts.append("domain") - - headers.append("Rule") - sorts.append("rule") - - try: - rows.sort(key=itemgetter(sorts.index(sort))) - except ValueError: - pass - - rows.insert(0, headers) - widths = [max(len(row[i]) for row in rows) for i in range(len(headers))] - rows.insert(1, ["-" * w for w in widths]) - template = " ".join(f"{{{i}:<{w}}}" for i, w in enumerate(widths)) - - for row in rows: - click.echo(template.format(*row)) - - -cli = FlaskGroup( - name="flask", - help="""\ -A general utility script for Flask applications. - -An application to load must be given with the '--app' option, -'FLASK_APP' environment variable, or with a 'wsgi.py' or 'app.py' file -in the current directory. -""", -) - - -def main() -> None: - cli.main() - - -if __name__ == "__main__": - main() diff --git a/serverenv/lib/python3.9/site-packages/flask/config.py b/serverenv/lib/python3.9/site-packages/flask/config.py deleted file mode 100644 index 34ef1a5..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/config.py +++ /dev/null @@ -1,367 +0,0 @@ -from __future__ import annotations - -import errno -import json -import os -import types -import typing as t - -from werkzeug.utils import import_string - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .sansio.app import App - - -T = t.TypeVar("T") - - -class ConfigAttribute(t.Generic[T]): - """Makes an attribute forward to the config""" - - def __init__( - self, name: str, get_converter: t.Callable[[t.Any], T] | None = None - ) -> None: - self.__name__ = name - self.get_converter = get_converter - - @t.overload - def __get__(self, obj: None, owner: None) -> te.Self: ... - - @t.overload - def __get__(self, obj: App, owner: type[App]) -> T: ... - - def __get__(self, obj: App | None, owner: type[App] | None = None) -> T | te.Self: - if obj is None: - return self - - rv = obj.config[self.__name__] - - if self.get_converter is not None: - rv = self.get_converter(rv) - - return rv # type: ignore[no-any-return] - - def __set__(self, obj: App, value: t.Any) -> None: - obj.config[self.__name__] = value - - -class Config(dict): # type: ignore[type-arg] - """Works exactly like a dict but provides ways to fill it from files - or special dictionaries. There are two common patterns to populate the - config. - - Either you can fill the config from a config file:: - - app.config.from_pyfile('yourconfig.cfg') - - Or alternatively you can define the configuration options in the - module that calls :meth:`from_object` or provide an import path to - a module that should be loaded. It is also possible to tell it to - use the same module and with that provide the configuration values - just before the call:: - - DEBUG = True - SECRET_KEY = 'development key' - app.config.from_object(__name__) - - In both cases (loading from any Python file or loading from modules), - only uppercase keys are added to the config. This makes it possible to use - lowercase values in the config file for temporary values that are not added - to the config or to define the config keys in the same file that implements - the application. - - Probably the most interesting way to load configurations is from an - environment variable pointing to a file:: - - app.config.from_envvar('YOURAPPLICATION_SETTINGS') - - In this case before launching the application you have to set this - environment variable to the file you want to use. On Linux and OS X - use the export statement:: - - export YOURAPPLICATION_SETTINGS='/path/to/config/file' - - On windows use `set` instead. - - :param root_path: path to which files are read relative from. When the - config object is created by the application, this is - the application's :attr:`~flask.Flask.root_path`. - :param defaults: an optional dictionary of default values - """ - - def __init__( - self, - root_path: str | os.PathLike[str], - defaults: dict[str, t.Any] | None = None, - ) -> None: - super().__init__(defaults or {}) - self.root_path = root_path - - def from_envvar(self, variable_name: str, silent: bool = False) -> bool: - """Loads a configuration from an environment variable pointing to - a configuration file. This is basically just a shortcut with nicer - error messages for this line of code:: - - app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) - - :param variable_name: name of the environment variable - :param silent: set to ``True`` if you want silent failure for missing - files. - :return: ``True`` if the file was loaded successfully. - """ - rv = os.environ.get(variable_name) - if not rv: - if silent: - return False - raise RuntimeError( - f"The environment variable {variable_name!r} is not set" - " and as such configuration could not be loaded. Set" - " this variable and make it point to a configuration" - " file" - ) - return self.from_pyfile(rv, silent=silent) - - def from_prefixed_env( - self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads - ) -> bool: - """Load any environment variables that start with ``FLASK_``, - dropping the prefix from the env key for the config key. Values - are passed through a loading function to attempt to convert them - to more specific types than strings. - - Keys are loaded in :func:`sorted` order. - - The default loading function attempts to parse values as any - valid JSON type, including dicts and lists. - - Specific items in nested dicts can be set by separating the - keys with double underscores (``__``). If an intermediate key - doesn't exist, it will be initialized to an empty dict. - - :param prefix: Load env vars that start with this prefix, - separated with an underscore (``_``). - :param loads: Pass each string value to this function and use - the returned value as the config value. If any error is - raised it is ignored and the value remains a string. The - default is :func:`json.loads`. - - .. versionadded:: 2.1 - """ - prefix = f"{prefix}_" - - for key in sorted(os.environ): - if not key.startswith(prefix): - continue - - value = os.environ[key] - key = key.removeprefix(prefix) - - try: - value = loads(value) - except Exception: - # Keep the value as a string if loading failed. - pass - - if "__" not in key: - # A non-nested key, set directly. - self[key] = value - continue - - # Traverse nested dictionaries with keys separated by "__". - current = self - *parts, tail = key.split("__") - - for part in parts: - # If an intermediate dict does not exist, create it. - if part not in current: - current[part] = {} - - current = current[part] - - current[tail] = value - - return True - - def from_pyfile( - self, filename: str | os.PathLike[str], silent: bool = False - ) -> bool: - """Updates the values in the config from a Python file. This function - behaves as if the file was imported as module with the - :meth:`from_object` function. - - :param filename: the filename of the config. This can either be an - absolute filename or a filename relative to the - root path. - :param silent: set to ``True`` if you want silent failure for missing - files. - :return: ``True`` if the file was loaded successfully. - - .. versionadded:: 0.7 - `silent` parameter. - """ - filename = os.path.join(self.root_path, filename) - d = types.ModuleType("config") - d.__file__ = filename - try: - with open(filename, mode="rb") as config_file: - exec(compile(config_file.read(), filename, "exec"), d.__dict__) - except OSError as e: - if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): - return False - e.strerror = f"Unable to load configuration file ({e.strerror})" - raise - self.from_object(d) - return True - - def from_object(self, obj: object | str) -> None: - """Updates the values from the given object. An object can be of one - of the following two types: - - - a string: in this case the object with that name will be imported - - an actual object reference: that object is used directly - - Objects are usually either modules or classes. :meth:`from_object` - loads only the uppercase attributes of the module/class. A ``dict`` - object will not work with :meth:`from_object` because the keys of a - ``dict`` are not attributes of the ``dict`` class. - - Example of module-based configuration:: - - app.config.from_object('yourapplication.default_config') - from yourapplication import default_config - app.config.from_object(default_config) - - Nothing is done to the object before loading. If the object is a - class and has ``@property`` attributes, it needs to be - instantiated before being passed to this method. - - You should not use this function to load the actual configuration but - rather configuration defaults. The actual config should be loaded - with :meth:`from_pyfile` and ideally from a location not within the - package because the package might be installed system wide. - - See :ref:`config-dev-prod` for an example of class-based configuration - using :meth:`from_object`. - - :param obj: an import name or object - """ - if isinstance(obj, str): - obj = import_string(obj) - for key in dir(obj): - if key.isupper(): - self[key] = getattr(obj, key) - - def from_file( - self, - filename: str | os.PathLike[str], - load: t.Callable[[t.IO[t.Any]], t.Mapping[str, t.Any]], - silent: bool = False, - text: bool = True, - ) -> bool: - """Update the values in the config from a file that is loaded - using the ``load`` parameter. The loaded data is passed to the - :meth:`from_mapping` method. - - .. code-block:: python - - import json - app.config.from_file("config.json", load=json.load) - - import tomllib - app.config.from_file("config.toml", load=tomllib.load, text=False) - - :param filename: The path to the data file. This can be an - absolute path or relative to the config root path. - :param load: A callable that takes a file handle and returns a - mapping of loaded data from the file. - :type load: ``Callable[[Reader], Mapping]`` where ``Reader`` - implements a ``read`` method. - :param silent: Ignore the file if it doesn't exist. - :param text: Open the file in text or binary mode. - :return: ``True`` if the file was loaded successfully. - - .. versionchanged:: 2.3 - The ``text`` parameter was added. - - .. versionadded:: 2.0 - """ - filename = os.path.join(self.root_path, filename) - - try: - with open(filename, "r" if text else "rb") as f: - obj = load(f) - except OSError as e: - if silent and e.errno in (errno.ENOENT, errno.EISDIR): - return False - - e.strerror = f"Unable to load configuration file ({e.strerror})" - raise - - return self.from_mapping(obj) - - def from_mapping( - self, mapping: t.Mapping[str, t.Any] | None = None, **kwargs: t.Any - ) -> bool: - """Updates the config like :meth:`update` ignoring items with - non-upper keys. - - :return: Always returns ``True``. - - .. versionadded:: 0.11 - """ - mappings: dict[str, t.Any] = {} - if mapping is not None: - mappings.update(mapping) - mappings.update(kwargs) - for key, value in mappings.items(): - if key.isupper(): - self[key] = value - return True - - def get_namespace( - self, namespace: str, lowercase: bool = True, trim_namespace: bool = True - ) -> dict[str, t.Any]: - """Returns a dictionary containing a subset of configuration options - that match the specified namespace/prefix. Example usage:: - - app.config['IMAGE_STORE_TYPE'] = 'fs' - app.config['IMAGE_STORE_PATH'] = '/var/app/images' - app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' - image_store_config = app.config.get_namespace('IMAGE_STORE_') - - The resulting dictionary `image_store_config` would look like:: - - { - 'type': 'fs', - 'path': '/var/app/images', - 'base_url': 'http://img.website.com' - } - - This is often useful when configuration options map directly to - keyword arguments in functions or class constructors. - - :param namespace: a configuration namespace - :param lowercase: a flag indicating if the keys of the resulting - dictionary should be lowercase - :param trim_namespace: a flag indicating if the keys of the resulting - dictionary should not include the namespace - - .. versionadded:: 0.11 - """ - rv = {} - for k, v in self.items(): - if not k.startswith(namespace): - continue - if trim_namespace: - key = k[len(namespace) :] - else: - key = k - if lowercase: - key = key.lower() - rv[key] = v - return rv - - def __repr__(self) -> str: - return f"<{type(self).__name__} {dict.__repr__(self)}>" diff --git a/serverenv/lib/python3.9/site-packages/flask/ctx.py b/serverenv/lib/python3.9/site-packages/flask/ctx.py deleted file mode 100644 index 9b164d3..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/ctx.py +++ /dev/null @@ -1,449 +0,0 @@ -from __future__ import annotations - -import contextvars -import sys -import typing as t -from functools import update_wrapper -from types import TracebackType - -from werkzeug.exceptions import HTTPException - -from . import typing as ft -from .globals import _cv_app -from .globals import _cv_request -from .signals import appcontext_popped -from .signals import appcontext_pushed - -if t.TYPE_CHECKING: # pragma: no cover - from _typeshed.wsgi import WSGIEnvironment - - from .app import Flask - from .sessions import SessionMixin - from .wrappers import Request - - -# a singleton sentinel value for parameter defaults -_sentinel = object() - - -class _AppCtxGlobals: - """A plain object. Used as a namespace for storing data during an - application context. - - Creating an app context automatically creates this object, which is - made available as the :data:`g` proxy. - - .. describe:: 'key' in g - - Check whether an attribute is present. - - .. versionadded:: 0.10 - - .. describe:: iter(g) - - Return an iterator over the attribute names. - - .. versionadded:: 0.10 - """ - - # Define attr methods to let mypy know this is a namespace object - # that has arbitrary attributes. - - def __getattr__(self, name: str) -> t.Any: - try: - return self.__dict__[name] - except KeyError: - raise AttributeError(name) from None - - def __setattr__(self, name: str, value: t.Any) -> None: - self.__dict__[name] = value - - def __delattr__(self, name: str) -> None: - try: - del self.__dict__[name] - except KeyError: - raise AttributeError(name) from None - - def get(self, name: str, default: t.Any | None = None) -> t.Any: - """Get an attribute by name, or a default value. Like - :meth:`dict.get`. - - :param name: Name of attribute to get. - :param default: Value to return if the attribute is not present. - - .. versionadded:: 0.10 - """ - return self.__dict__.get(name, default) - - def pop(self, name: str, default: t.Any = _sentinel) -> t.Any: - """Get and remove an attribute by name. Like :meth:`dict.pop`. - - :param name: Name of attribute to pop. - :param default: Value to return if the attribute is not present, - instead of raising a ``KeyError``. - - .. versionadded:: 0.11 - """ - if default is _sentinel: - return self.__dict__.pop(name) - else: - return self.__dict__.pop(name, default) - - def setdefault(self, name: str, default: t.Any = None) -> t.Any: - """Get the value of an attribute if it is present, otherwise - set and return a default value. Like :meth:`dict.setdefault`. - - :param name: Name of attribute to get. - :param default: Value to set and return if the attribute is not - present. - - .. versionadded:: 0.11 - """ - return self.__dict__.setdefault(name, default) - - def __contains__(self, item: str) -> bool: - return item in self.__dict__ - - def __iter__(self) -> t.Iterator[str]: - return iter(self.__dict__) - - def __repr__(self) -> str: - ctx = _cv_app.get(None) - if ctx is not None: - return f"" - return object.__repr__(self) - - -def after_this_request( - f: ft.AfterRequestCallable[t.Any], -) -> ft.AfterRequestCallable[t.Any]: - """Executes a function after this request. This is useful to modify - response objects. The function is passed the response object and has - to return the same or a new one. - - Example:: - - @app.route('/') - def index(): - @after_this_request - def add_header(response): - response.headers['X-Foo'] = 'Parachute' - return response - return 'Hello World!' - - This is more useful if a function other than the view function wants to - modify a response. For instance think of a decorator that wants to add - some headers without converting the return value into a response object. - - .. versionadded:: 0.9 - """ - ctx = _cv_request.get(None) - - if ctx is None: - raise RuntimeError( - "'after_this_request' can only be used when a request" - " context is active, such as in a view function." - ) - - ctx._after_request_functions.append(f) - return f - - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) - - -def copy_current_request_context(f: F) -> F: - """A helper function that decorates a function to retain the current - request context. This is useful when working with greenlets. The moment - the function is decorated a copy of the request context is created and - then pushed when the function is called. The current session is also - included in the copied request context. - - Example:: - - import gevent - from flask import copy_current_request_context - - @app.route('/') - def index(): - @copy_current_request_context - def do_some_work(): - # do some work here, it can access flask.request or - # flask.session like you would otherwise in the view function. - ... - gevent.spawn(do_some_work) - return 'Regular response' - - .. versionadded:: 0.10 - """ - ctx = _cv_request.get(None) - - if ctx is None: - raise RuntimeError( - "'copy_current_request_context' can only be used when a" - " request context is active, such as in a view function." - ) - - ctx = ctx.copy() - - def wrapper(*args: t.Any, **kwargs: t.Any) -> t.Any: - with ctx: # type: ignore[union-attr] - return ctx.app.ensure_sync(f)(*args, **kwargs) # type: ignore[union-attr] - - return update_wrapper(wrapper, f) # type: ignore[return-value] - - -def has_request_context() -> bool: - """If you have code that wants to test if a request context is there or - not this function can be used. For instance, you may want to take advantage - of request information if the request object is available, but fail - silently if it is unavailable. - - :: - - class User(db.Model): - - def __init__(self, username, remote_addr=None): - self.username = username - if remote_addr is None and has_request_context(): - remote_addr = request.remote_addr - self.remote_addr = remote_addr - - Alternatively you can also just test any of the context bound objects - (such as :class:`request` or :class:`g`) for truthness:: - - class User(db.Model): - - def __init__(self, username, remote_addr=None): - self.username = username - if remote_addr is None and request: - remote_addr = request.remote_addr - self.remote_addr = remote_addr - - .. versionadded:: 0.7 - """ - return _cv_request.get(None) is not None - - -def has_app_context() -> bool: - """Works like :func:`has_request_context` but for the application - context. You can also just do a boolean check on the - :data:`current_app` object instead. - - .. versionadded:: 0.9 - """ - return _cv_app.get(None) is not None - - -class AppContext: - """The app context contains application-specific information. An app - context is created and pushed at the beginning of each request if - one is not already active. An app context is also pushed when - running CLI commands. - """ - - def __init__(self, app: Flask) -> None: - self.app = app - self.url_adapter = app.create_url_adapter(None) - self.g: _AppCtxGlobals = app.app_ctx_globals_class() - self._cv_tokens: list[contextvars.Token[AppContext]] = [] - - def push(self) -> None: - """Binds the app context to the current context.""" - self._cv_tokens.append(_cv_app.set(self)) - appcontext_pushed.send(self.app, _async_wrapper=self.app.ensure_sync) - - def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore - """Pops the app context.""" - try: - if len(self._cv_tokens) == 1: - if exc is _sentinel: - exc = sys.exc_info()[1] - self.app.do_teardown_appcontext(exc) - finally: - ctx = _cv_app.get() - _cv_app.reset(self._cv_tokens.pop()) - - if ctx is not self: - raise AssertionError( - f"Popped wrong app context. ({ctx!r} instead of {self!r})" - ) - - appcontext_popped.send(self.app, _async_wrapper=self.app.ensure_sync) - - def __enter__(self) -> AppContext: - self.push() - return self - - def __exit__( - self, - exc_type: type | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> None: - self.pop(exc_value) - - -class RequestContext: - """The request context contains per-request information. The Flask - app creates and pushes it at the beginning of the request, then pops - it at the end of the request. It will create the URL adapter and - request object for the WSGI environment provided. - - Do not attempt to use this class directly, instead use - :meth:`~flask.Flask.test_request_context` and - :meth:`~flask.Flask.request_context` to create this object. - - When the request context is popped, it will evaluate all the - functions registered on the application for teardown execution - (:meth:`~flask.Flask.teardown_request`). - - The request context is automatically popped at the end of the - request. When using the interactive debugger, the context will be - restored so ``request`` is still accessible. Similarly, the test - client can preserve the context after the request ends. However, - teardown functions may already have closed some resources such as - database connections. - """ - - def __init__( - self, - app: Flask, - environ: WSGIEnvironment, - request: Request | None = None, - session: SessionMixin | None = None, - ) -> None: - self.app = app - if request is None: - request = app.request_class(environ) - request.json_module = app.json - self.request: Request = request - self.url_adapter = None - try: - self.url_adapter = app.create_url_adapter(self.request) - except HTTPException as e: - self.request.routing_exception = e - self.flashes: list[tuple[str, str]] | None = None - self.session: SessionMixin | None = session - # Functions that should be executed after the request on the response - # object. These will be called before the regular "after_request" - # functions. - self._after_request_functions: list[ft.AfterRequestCallable[t.Any]] = [] - - self._cv_tokens: list[ - tuple[contextvars.Token[RequestContext], AppContext | None] - ] = [] - - def copy(self) -> RequestContext: - """Creates a copy of this request context with the same request object. - This can be used to move a request context to a different greenlet. - Because the actual request object is the same this cannot be used to - move a request context to a different thread unless access to the - request object is locked. - - .. versionadded:: 0.10 - - .. versionchanged:: 1.1 - The current session object is used instead of reloading the original - data. This prevents `flask.session` pointing to an out-of-date object. - """ - return self.__class__( - self.app, - environ=self.request.environ, - request=self.request, - session=self.session, - ) - - def match_request(self) -> None: - """Can be overridden by a subclass to hook into the matching - of the request. - """ - try: - result = self.url_adapter.match(return_rule=True) # type: ignore - self.request.url_rule, self.request.view_args = result # type: ignore - except HTTPException as e: - self.request.routing_exception = e - - def push(self) -> None: - # Before we push the request context we have to ensure that there - # is an application context. - app_ctx = _cv_app.get(None) - - if app_ctx is None or app_ctx.app is not self.app: - app_ctx = self.app.app_context() - app_ctx.push() - else: - app_ctx = None - - self._cv_tokens.append((_cv_request.set(self), app_ctx)) - - # Open the session at the moment that the request context is available. - # This allows a custom open_session method to use the request context. - # Only open a new session if this is the first time the request was - # pushed, otherwise stream_with_context loses the session. - if self.session is None: - session_interface = self.app.session_interface - self.session = session_interface.open_session(self.app, self.request) - - if self.session is None: - self.session = session_interface.make_null_session(self.app) - - # Match the request URL after loading the session, so that the - # session is available in custom URL converters. - if self.url_adapter is not None: - self.match_request() - - def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore - """Pops the request context and unbinds it by doing that. This will - also trigger the execution of functions registered by the - :meth:`~flask.Flask.teardown_request` decorator. - - .. versionchanged:: 0.9 - Added the `exc` argument. - """ - clear_request = len(self._cv_tokens) == 1 - - try: - if clear_request: - if exc is _sentinel: - exc = sys.exc_info()[1] - self.app.do_teardown_request(exc) - - request_close = getattr(self.request, "close", None) - if request_close is not None: - request_close() - finally: - ctx = _cv_request.get() - token, app_ctx = self._cv_tokens.pop() - _cv_request.reset(token) - - # get rid of circular dependencies at the end of the request - # so that we don't require the GC to be active. - if clear_request: - ctx.request.environ["werkzeug.request"] = None - - if app_ctx is not None: - app_ctx.pop(exc) - - if ctx is not self: - raise AssertionError( - f"Popped wrong request context. ({ctx!r} instead of {self!r})" - ) - - def __enter__(self) -> RequestContext: - self.push() - return self - - def __exit__( - self, - exc_type: type | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> None: - self.pop(exc_value) - - def __repr__(self) -> str: - return ( - f"<{type(self).__name__} {self.request.url!r}" - f" [{self.request.method}] of {self.app.name}>" - ) diff --git a/serverenv/lib/python3.9/site-packages/flask/debughelpers.py b/serverenv/lib/python3.9/site-packages/flask/debughelpers.py deleted file mode 100644 index 2c8c4c4..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/debughelpers.py +++ /dev/null @@ -1,178 +0,0 @@ -from __future__ import annotations - -import typing as t - -from jinja2.loaders import BaseLoader -from werkzeug.routing import RequestRedirect - -from .blueprints import Blueprint -from .globals import request_ctx -from .sansio.app import App - -if t.TYPE_CHECKING: - from .sansio.scaffold import Scaffold - from .wrappers import Request - - -class UnexpectedUnicodeError(AssertionError, UnicodeError): - """Raised in places where we want some better error reporting for - unexpected unicode or binary data. - """ - - -class DebugFilesKeyError(KeyError, AssertionError): - """Raised from request.files during debugging. The idea is that it can - provide a better error message than just a generic KeyError/BadRequest. - """ - - def __init__(self, request: Request, key: str) -> None: - form_matches = request.form.getlist(key) - buf = [ - f"You tried to access the file {key!r} in the request.files" - " dictionary but it does not exist. The mimetype for the" - f" request is {request.mimetype!r} instead of" - " 'multipart/form-data' which means that no file contents" - " were transmitted. To fix this error you should provide" - ' enctype="multipart/form-data" in your form.' - ] - if form_matches: - names = ", ".join(repr(x) for x in form_matches) - buf.append( - "\n\nThe browser instead transmitted some file names. " - f"This was submitted: {names}" - ) - self.msg = "".join(buf) - - def __str__(self) -> str: - return self.msg - - -class FormDataRoutingRedirect(AssertionError): - """This exception is raised in debug mode if a routing redirect - would cause the browser to drop the method or body. This happens - when method is not GET, HEAD or OPTIONS and the status code is not - 307 or 308. - """ - - def __init__(self, request: Request) -> None: - exc = request.routing_exception - assert isinstance(exc, RequestRedirect) - buf = [ - f"A request was sent to '{request.url}', but routing issued" - f" a redirect to the canonical URL '{exc.new_url}'." - ] - - if f"{request.base_url}/" == exc.new_url.partition("?")[0]: - buf.append( - " The URL was defined with a trailing slash. Flask" - " will redirect to the URL with a trailing slash if it" - " was accessed without one." - ) - - buf.append( - " Send requests to the canonical URL, or use 307 or 308 for" - " routing redirects. Otherwise, browsers will drop form" - " data.\n\n" - "This exception is only raised in debug mode." - ) - super().__init__("".join(buf)) - - -def attach_enctype_error_multidict(request: Request) -> None: - """Patch ``request.files.__getitem__`` to raise a descriptive error - about ``enctype=multipart/form-data``. - - :param request: The request to patch. - :meta private: - """ - oldcls = request.files.__class__ - - class newcls(oldcls): # type: ignore[valid-type, misc] - def __getitem__(self, key: str) -> t.Any: - try: - return super().__getitem__(key) - except KeyError as e: - if key not in request.form: - raise - - raise DebugFilesKeyError(request, key).with_traceback( - e.__traceback__ - ) from None - - newcls.__name__ = oldcls.__name__ - newcls.__module__ = oldcls.__module__ - request.files.__class__ = newcls - - -def _dump_loader_info(loader: BaseLoader) -> t.Iterator[str]: - yield f"class: {type(loader).__module__}.{type(loader).__name__}" - for key, value in sorted(loader.__dict__.items()): - if key.startswith("_"): - continue - if isinstance(value, (tuple, list)): - if not all(isinstance(x, str) for x in value): - continue - yield f"{key}:" - for item in value: - yield f" - {item}" - continue - elif not isinstance(value, (str, int, float, bool)): - continue - yield f"{key}: {value!r}" - - -def explain_template_loading_attempts( - app: App, - template: str, - attempts: list[ - tuple[ - BaseLoader, - Scaffold, - tuple[str, str | None, t.Callable[[], bool] | None] | None, - ] - ], -) -> None: - """This should help developers understand what failed""" - info = [f"Locating template {template!r}:"] - total_found = 0 - blueprint = None - if request_ctx and request_ctx.request.blueprint is not None: - blueprint = request_ctx.request.blueprint - - for idx, (loader, srcobj, triple) in enumerate(attempts): - if isinstance(srcobj, App): - src_info = f"application {srcobj.import_name!r}" - elif isinstance(srcobj, Blueprint): - src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})" - else: - src_info = repr(srcobj) - - info.append(f"{idx + 1:5}: trying loader of {src_info}") - - for line in _dump_loader_info(loader): - info.append(f" {line}") - - if triple is None: - detail = "no match" - else: - detail = f"found ({triple[1] or ''!r})" - total_found += 1 - info.append(f" -> {detail}") - - seems_fishy = False - if total_found == 0: - info.append("Error: the template could not be found.") - seems_fishy = True - elif total_found > 1: - info.append("Warning: multiple loaders returned a match for the template.") - seems_fishy = True - - if blueprint is not None and seems_fishy: - info.append( - " The template was looked up from an endpoint that belongs" - f" to the blueprint {blueprint!r}." - ) - info.append(" Maybe you did not place a template in the right folder?") - info.append(" See https://flask.palletsprojects.com/blueprints/#templates") - - app.logger.info("\n".join(info)) diff --git a/serverenv/lib/python3.9/site-packages/flask/globals.py b/serverenv/lib/python3.9/site-packages/flask/globals.py deleted file mode 100644 index e2c410c..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/globals.py +++ /dev/null @@ -1,51 +0,0 @@ -from __future__ import annotations - -import typing as t -from contextvars import ContextVar - -from werkzeug.local import LocalProxy - -if t.TYPE_CHECKING: # pragma: no cover - from .app import Flask - from .ctx import _AppCtxGlobals - from .ctx import AppContext - from .ctx import RequestContext - from .sessions import SessionMixin - from .wrappers import Request - - -_no_app_msg = """\ -Working outside of application context. - -This typically means that you attempted to use functionality that needed -the current application. To solve this, set up an application context -with app.app_context(). See the documentation for more information.\ -""" -_cv_app: ContextVar[AppContext] = ContextVar("flask.app_ctx") -app_ctx: AppContext = LocalProxy( # type: ignore[assignment] - _cv_app, unbound_message=_no_app_msg -) -current_app: Flask = LocalProxy( # type: ignore[assignment] - _cv_app, "app", unbound_message=_no_app_msg -) -g: _AppCtxGlobals = LocalProxy( # type: ignore[assignment] - _cv_app, "g", unbound_message=_no_app_msg -) - -_no_req_msg = """\ -Working outside of request context. - -This typically means that you attempted to use functionality that needed -an active HTTP request. Consult the documentation on testing for -information about how to avoid this problem.\ -""" -_cv_request: ContextVar[RequestContext] = ContextVar("flask.request_ctx") -request_ctx: RequestContext = LocalProxy( # type: ignore[assignment] - _cv_request, unbound_message=_no_req_msg -) -request: Request = LocalProxy( # type: ignore[assignment] - _cv_request, "request", unbound_message=_no_req_msg -) -session: SessionMixin = LocalProxy( # type: ignore[assignment] - _cv_request, "session", unbound_message=_no_req_msg -) diff --git a/serverenv/lib/python3.9/site-packages/flask/helpers.py b/serverenv/lib/python3.9/site-packages/flask/helpers.py deleted file mode 100644 index a6b7e15..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/helpers.py +++ /dev/null @@ -1,634 +0,0 @@ -from __future__ import annotations - -import importlib.util -import os -import sys -import typing as t -from datetime import datetime -from functools import cache -from functools import update_wrapper - -import werkzeug.utils -from werkzeug.exceptions import abort as _wz_abort -from werkzeug.utils import redirect as _wz_redirect -from werkzeug.wrappers import Response as BaseResponse - -from .globals import _cv_request -from .globals import current_app -from .globals import request -from .globals import request_ctx -from .globals import session -from .signals import message_flashed - -if t.TYPE_CHECKING: # pragma: no cover - from .wrappers import Response - - -def get_debug_flag() -> bool: - """Get whether debug mode should be enabled for the app, indicated by the - :envvar:`FLASK_DEBUG` environment variable. The default is ``False``. - """ - val = os.environ.get("FLASK_DEBUG") - return bool(val and val.lower() not in {"0", "false", "no"}) - - -def get_load_dotenv(default: bool = True) -> bool: - """Get whether the user has disabled loading default dotenv files by - setting :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load - the files. - - :param default: What to return if the env var isn't set. - """ - val = os.environ.get("FLASK_SKIP_DOTENV") - - if not val: - return default - - return val.lower() in ("0", "false", "no") - - -@t.overload -def stream_with_context( - generator_or_function: t.Iterator[t.AnyStr], -) -> t.Iterator[t.AnyStr]: ... - - -@t.overload -def stream_with_context( - generator_or_function: t.Callable[..., t.Iterator[t.AnyStr]], -) -> t.Callable[[t.Iterator[t.AnyStr]], t.Iterator[t.AnyStr]]: ... - - -def stream_with_context( - generator_or_function: t.Iterator[t.AnyStr] | t.Callable[..., t.Iterator[t.AnyStr]], -) -> t.Iterator[t.AnyStr] | t.Callable[[t.Iterator[t.AnyStr]], t.Iterator[t.AnyStr]]: - """Request contexts disappear when the response is started on the server. - This is done for efficiency reasons and to make it less likely to encounter - memory leaks with badly written WSGI middlewares. The downside is that if - you are using streamed responses, the generator cannot access request bound - information any more. - - This function however can help you keep the context around for longer:: - - from flask import stream_with_context, request, Response - - @app.route('/stream') - def streamed_response(): - @stream_with_context - def generate(): - yield 'Hello ' - yield request.args['name'] - yield '!' - return Response(generate()) - - Alternatively it can also be used around a specific generator:: - - from flask import stream_with_context, request, Response - - @app.route('/stream') - def streamed_response(): - def generate(): - yield 'Hello ' - yield request.args['name'] - yield '!' - return Response(stream_with_context(generate())) - - .. versionadded:: 0.9 - """ - try: - gen = iter(generator_or_function) # type: ignore[arg-type] - except TypeError: - - def decorator(*args: t.Any, **kwargs: t.Any) -> t.Any: - gen = generator_or_function(*args, **kwargs) # type: ignore[operator] - return stream_with_context(gen) - - return update_wrapper(decorator, generator_or_function) # type: ignore[arg-type] - - def generator() -> t.Iterator[t.AnyStr | None]: - ctx = _cv_request.get(None) - if ctx is None: - raise RuntimeError( - "'stream_with_context' can only be used when a request" - " context is active, such as in a view function." - ) - with ctx: - # Dummy sentinel. Has to be inside the context block or we're - # not actually keeping the context around. - yield None - - # The try/finally is here so that if someone passes a WSGI level - # iterator in we're still running the cleanup logic. Generators - # don't need that because they are closed on their destruction - # automatically. - try: - yield from gen - finally: - if hasattr(gen, "close"): - gen.close() - - # The trick is to start the generator. Then the code execution runs until - # the first dummy None is yielded at which point the context was already - # pushed. This item is discarded. Then when the iteration continues the - # real generator is executed. - wrapped_g = generator() - next(wrapped_g) - return wrapped_g # type: ignore[return-value] - - -def make_response(*args: t.Any) -> Response: - """Sometimes it is necessary to set additional headers in a view. Because - views do not have to return response objects but can return a value that - is converted into a response object by Flask itself, it becomes tricky to - add headers to it. This function can be called instead of using a return - and you will get a response object which you can use to attach headers. - - If view looked like this and you want to add a new header:: - - def index(): - return render_template('index.html', foo=42) - - You can now do something like this:: - - def index(): - response = make_response(render_template('index.html', foo=42)) - response.headers['X-Parachutes'] = 'parachutes are cool' - return response - - This function accepts the very same arguments you can return from a - view function. This for example creates a response with a 404 error - code:: - - response = make_response(render_template('not_found.html'), 404) - - The other use case of this function is to force the return value of a - view function into a response which is helpful with view - decorators:: - - response = make_response(view_function()) - response.headers['X-Parachutes'] = 'parachutes are cool' - - Internally this function does the following things: - - - if no arguments are passed, it creates a new response argument - - if one argument is passed, :meth:`flask.Flask.make_response` - is invoked with it. - - if more than one argument is passed, the arguments are passed - to the :meth:`flask.Flask.make_response` function as tuple. - - .. versionadded:: 0.6 - """ - if not args: - return current_app.response_class() - if len(args) == 1: - args = args[0] - return current_app.make_response(args) - - -def url_for( - endpoint: str, - *, - _anchor: str | None = None, - _method: str | None = None, - _scheme: str | None = None, - _external: bool | None = None, - **values: t.Any, -) -> str: - """Generate a URL to the given endpoint with the given values. - - This requires an active request or application context, and calls - :meth:`current_app.url_for() `. See that method - for full documentation. - - :param endpoint: The endpoint name associated with the URL to - generate. If this starts with a ``.``, the current blueprint - name (if any) will be used. - :param _anchor: If given, append this as ``#anchor`` to the URL. - :param _method: If given, generate the URL associated with this - method for the endpoint. - :param _scheme: If given, the URL will have this scheme if it is - external. - :param _external: If given, prefer the URL to be internal (False) or - require it to be external (True). External URLs include the - scheme and domain. When not in an active request, URLs are - external by default. - :param values: Values to use for the variable parts of the URL rule. - Unknown keys are appended as query string arguments, like - ``?a=b&c=d``. - - .. versionchanged:: 2.2 - Calls ``current_app.url_for``, allowing an app to override the - behavior. - - .. versionchanged:: 0.10 - The ``_scheme`` parameter was added. - - .. versionchanged:: 0.9 - The ``_anchor`` and ``_method`` parameters were added. - - .. versionchanged:: 0.9 - Calls ``app.handle_url_build_error`` on build errors. - """ - return current_app.url_for( - endpoint, - _anchor=_anchor, - _method=_method, - _scheme=_scheme, - _external=_external, - **values, - ) - - -def redirect( - location: str, code: int = 302, Response: type[BaseResponse] | None = None -) -> BaseResponse: - """Create a redirect response object. - - If :data:`~flask.current_app` is available, it will use its - :meth:`~flask.Flask.redirect` method, otherwise it will use - :func:`werkzeug.utils.redirect`. - - :param location: The URL to redirect to. - :param code: The status code for the redirect. - :param Response: The response class to use. Not used when - ``current_app`` is active, which uses ``app.response_class``. - - .. versionadded:: 2.2 - Calls ``current_app.redirect`` if available instead of always - using Werkzeug's default ``redirect``. - """ - if current_app: - return current_app.redirect(location, code=code) - - return _wz_redirect(location, code=code, Response=Response) - - -def abort(code: int | BaseResponse, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: - """Raise an :exc:`~werkzeug.exceptions.HTTPException` for the given - status code. - - If :data:`~flask.current_app` is available, it will call its - :attr:`~flask.Flask.aborter` object, otherwise it will use - :func:`werkzeug.exceptions.abort`. - - :param code: The status code for the exception, which must be - registered in ``app.aborter``. - :param args: Passed to the exception. - :param kwargs: Passed to the exception. - - .. versionadded:: 2.2 - Calls ``current_app.aborter`` if available instead of always - using Werkzeug's default ``abort``. - """ - if current_app: - current_app.aborter(code, *args, **kwargs) - - _wz_abort(code, *args, **kwargs) - - -def get_template_attribute(template_name: str, attribute: str) -> t.Any: - """Loads a macro (or variable) a template exports. This can be used to - invoke a macro from within Python code. If you for example have a - template named :file:`_cider.html` with the following contents: - - .. sourcecode:: html+jinja - - {% macro hello(name) %}Hello {{ name }}!{% endmacro %} - - You can access this from Python code like this:: - - hello = get_template_attribute('_cider.html', 'hello') - return hello('World') - - .. versionadded:: 0.2 - - :param template_name: the name of the template - :param attribute: the name of the variable of macro to access - """ - return getattr(current_app.jinja_env.get_template(template_name).module, attribute) - - -def flash(message: str, category: str = "message") -> None: - """Flashes a message to the next request. In order to remove the - flashed message from the session and to display it to the user, - the template has to call :func:`get_flashed_messages`. - - .. versionchanged:: 0.3 - `category` parameter added. - - :param message: the message to be flashed. - :param category: the category for the message. The following values - are recommended: ``'message'`` for any kind of message, - ``'error'`` for errors, ``'info'`` for information - messages and ``'warning'`` for warnings. However any - kind of string can be used as category. - """ - # Original implementation: - # - # session.setdefault('_flashes', []).append((category, message)) - # - # This assumed that changes made to mutable structures in the session are - # always in sync with the session object, which is not true for session - # implementations that use external storage for keeping their keys/values. - flashes = session.get("_flashes", []) - flashes.append((category, message)) - session["_flashes"] = flashes - app = current_app._get_current_object() # type: ignore - message_flashed.send( - app, - _async_wrapper=app.ensure_sync, - message=message, - category=category, - ) - - -def get_flashed_messages( - with_categories: bool = False, category_filter: t.Iterable[str] = () -) -> list[str] | list[tuple[str, str]]: - """Pulls all flashed messages from the session and returns them. - Further calls in the same request to the function will return - the same messages. By default just the messages are returned, - but when `with_categories` is set to ``True``, the return value will - be a list of tuples in the form ``(category, message)`` instead. - - Filter the flashed messages to one or more categories by providing those - categories in `category_filter`. This allows rendering categories in - separate html blocks. The `with_categories` and `category_filter` - arguments are distinct: - - * `with_categories` controls whether categories are returned with message - text (``True`` gives a tuple, where ``False`` gives just the message text). - * `category_filter` filters the messages down to only those matching the - provided categories. - - See :doc:`/patterns/flashing` for examples. - - .. versionchanged:: 0.3 - `with_categories` parameter added. - - .. versionchanged:: 0.9 - `category_filter` parameter added. - - :param with_categories: set to ``True`` to also receive categories. - :param category_filter: filter of categories to limit return values. Only - categories in the list will be returned. - """ - flashes = request_ctx.flashes - if flashes is None: - flashes = session.pop("_flashes") if "_flashes" in session else [] - request_ctx.flashes = flashes - if category_filter: - flashes = list(filter(lambda f: f[0] in category_filter, flashes)) - if not with_categories: - return [x[1] for x in flashes] - return flashes - - -def _prepare_send_file_kwargs(**kwargs: t.Any) -> dict[str, t.Any]: - if kwargs.get("max_age") is None: - kwargs["max_age"] = current_app.get_send_file_max_age - - kwargs.update( - environ=request.environ, - use_x_sendfile=current_app.config["USE_X_SENDFILE"], - response_class=current_app.response_class, - _root_path=current_app.root_path, # type: ignore - ) - return kwargs - - -def send_file( - path_or_file: os.PathLike[t.AnyStr] | str | t.BinaryIO, - mimetype: str | None = None, - as_attachment: bool = False, - download_name: str | None = None, - conditional: bool = True, - etag: bool | str = True, - last_modified: datetime | int | float | None = None, - max_age: None | (int | t.Callable[[str | None], int | None]) = None, -) -> Response: - """Send the contents of a file to the client. - - The first argument can be a file path or a file-like object. Paths - are preferred in most cases because Werkzeug can manage the file and - get extra information from the path. Passing a file-like object - requires that the file is opened in binary mode, and is mostly - useful when building a file in memory with :class:`io.BytesIO`. - - Never pass file paths provided by a user. The path is assumed to be - trusted, so a user could craft a path to access a file you didn't - intend. Use :func:`send_from_directory` to safely serve - user-requested paths from within a directory. - - If the WSGI server sets a ``file_wrapper`` in ``environ``, it is - used, otherwise Werkzeug's built-in wrapper is used. Alternatively, - if the HTTP server supports ``X-Sendfile``, configuring Flask with - ``USE_X_SENDFILE = True`` will tell the server to send the given - path, which is much more efficient than reading it in Python. - - :param path_or_file: The path to the file to send, relative to the - current working directory if a relative path is given. - Alternatively, a file-like object opened in binary mode. Make - sure the file pointer is seeked to the start of the data. - :param mimetype: The MIME type to send for the file. If not - provided, it will try to detect it from the file name. - :param as_attachment: Indicate to a browser that it should offer to - save the file instead of displaying it. - :param download_name: The default name browsers will use when saving - the file. Defaults to the passed file name. - :param conditional: Enable conditional and range responses based on - request headers. Requires passing a file path and ``environ``. - :param etag: Calculate an ETag for the file, which requires passing - a file path. Can also be a string to use instead. - :param last_modified: The last modified time to send for the file, - in seconds. If not provided, it will try to detect it from the - file path. - :param max_age: How long the client should cache the file, in - seconds. If set, ``Cache-Control`` will be ``public``, otherwise - it will be ``no-cache`` to prefer conditional caching. - - .. versionchanged:: 2.0 - ``download_name`` replaces the ``attachment_filename`` - parameter. If ``as_attachment=False``, it is passed with - ``Content-Disposition: inline`` instead. - - .. versionchanged:: 2.0 - ``max_age`` replaces the ``cache_timeout`` parameter. - ``conditional`` is enabled and ``max_age`` is not set by - default. - - .. versionchanged:: 2.0 - ``etag`` replaces the ``add_etags`` parameter. It can be a - string to use instead of generating one. - - .. versionchanged:: 2.0 - Passing a file-like object that inherits from - :class:`~io.TextIOBase` will raise a :exc:`ValueError` rather - than sending an empty file. - - .. versionadded:: 2.0 - Moved the implementation to Werkzeug. This is now a wrapper to - pass some Flask-specific arguments. - - .. versionchanged:: 1.1 - ``filename`` may be a :class:`~os.PathLike` object. - - .. versionchanged:: 1.1 - Passing a :class:`~io.BytesIO` object supports range requests. - - .. versionchanged:: 1.0.3 - Filenames are encoded with ASCII instead of Latin-1 for broader - compatibility with WSGI servers. - - .. versionchanged:: 1.0 - UTF-8 filenames as specified in :rfc:`2231` are supported. - - .. versionchanged:: 0.12 - The filename is no longer automatically inferred from file - objects. If you want to use automatic MIME and etag support, - pass a filename via ``filename_or_fp`` or - ``attachment_filename``. - - .. versionchanged:: 0.12 - ``attachment_filename`` is preferred over ``filename`` for MIME - detection. - - .. versionchanged:: 0.9 - ``cache_timeout`` defaults to - :meth:`Flask.get_send_file_max_age`. - - .. versionchanged:: 0.7 - MIME guessing and etag support for file-like objects was - removed because it was unreliable. Pass a filename if you are - able to, otherwise attach an etag yourself. - - .. versionchanged:: 0.5 - The ``add_etags``, ``cache_timeout`` and ``conditional`` - parameters were added. The default behavior is to add etags. - - .. versionadded:: 0.2 - """ - return werkzeug.utils.send_file( # type: ignore[return-value] - **_prepare_send_file_kwargs( - path_or_file=path_or_file, - environ=request.environ, - mimetype=mimetype, - as_attachment=as_attachment, - download_name=download_name, - conditional=conditional, - etag=etag, - last_modified=last_modified, - max_age=max_age, - ) - ) - - -def send_from_directory( - directory: os.PathLike[str] | str, - path: os.PathLike[str] | str, - **kwargs: t.Any, -) -> Response: - """Send a file from within a directory using :func:`send_file`. - - .. code-block:: python - - @app.route("/uploads/") - def download_file(name): - return send_from_directory( - app.config['UPLOAD_FOLDER'], name, as_attachment=True - ) - - This is a secure way to serve files from a folder, such as static - files or uploads. Uses :func:`~werkzeug.security.safe_join` to - ensure the path coming from the client is not maliciously crafted to - point outside the specified directory. - - If the final path does not point to an existing regular file, - raises a 404 :exc:`~werkzeug.exceptions.NotFound` error. - - :param directory: The directory that ``path`` must be located under, - relative to the current application's root path. This *must not* - be a value provided by the client, otherwise it becomes insecure. - :param path: The path to the file to send, relative to - ``directory``. - :param kwargs: Arguments to pass to :func:`send_file`. - - .. versionchanged:: 2.0 - ``path`` replaces the ``filename`` parameter. - - .. versionadded:: 2.0 - Moved the implementation to Werkzeug. This is now a wrapper to - pass some Flask-specific arguments. - - .. versionadded:: 0.5 - """ - return werkzeug.utils.send_from_directory( # type: ignore[return-value] - directory, path, **_prepare_send_file_kwargs(**kwargs) - ) - - -def get_root_path(import_name: str) -> str: - """Find the root path of a package, or the path that contains a - module. If it cannot be found, returns the current working - directory. - - Not to be confused with the value returned by :func:`find_package`. - - :meta private: - """ - # Module already imported and has a file attribute. Use that first. - mod = sys.modules.get(import_name) - - if mod is not None and hasattr(mod, "__file__") and mod.__file__ is not None: - return os.path.dirname(os.path.abspath(mod.__file__)) - - # Next attempt: check the loader. - try: - spec = importlib.util.find_spec(import_name) - - if spec is None: - raise ValueError - except (ImportError, ValueError): - loader = None - else: - loader = spec.loader - - # Loader does not exist or we're referring to an unloaded main - # module or a main module without path (interactive sessions), go - # with the current working directory. - if loader is None: - return os.getcwd() - - if hasattr(loader, "get_filename"): - filepath = loader.get_filename(import_name) # pyright: ignore - else: - # Fall back to imports. - __import__(import_name) - mod = sys.modules[import_name] - filepath = getattr(mod, "__file__", None) - - # If we don't have a file path it might be because it is a - # namespace package. In this case pick the root path from the - # first module that is contained in the package. - if filepath is None: - raise RuntimeError( - "No root path can be found for the provided module" - f" {import_name!r}. This can happen because the module" - " came from an import hook that does not provide file" - " name information or because it's a namespace package." - " In this case the root path needs to be explicitly" - " provided." - ) - - # filepath is import_name.py for a module, or __init__.py for a package. - return os.path.dirname(os.path.abspath(filepath)) # type: ignore[no-any-return] - - -@cache -def _split_blueprint_path(name: str) -> list[str]: - out: list[str] = [name] - - if "." in name: - out.extend(_split_blueprint_path(name.rpartition(".")[0])) - - return out diff --git a/serverenv/lib/python3.9/site-packages/flask/json/__init__.py b/serverenv/lib/python3.9/site-packages/flask/json/__init__.py deleted file mode 100644 index c0941d0..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/json/__init__.py +++ /dev/null @@ -1,170 +0,0 @@ -from __future__ import annotations - -import json as _json -import typing as t - -from ..globals import current_app -from .provider import _default - -if t.TYPE_CHECKING: # pragma: no cover - from ..wrappers import Response - - -def dumps(obj: t.Any, **kwargs: t.Any) -> str: - """Serialize data as JSON. - - If :data:`~flask.current_app` is available, it will use its - :meth:`app.json.dumps() ` - method, otherwise it will use :func:`json.dumps`. - - :param obj: The data to serialize. - :param kwargs: Arguments passed to the ``dumps`` implementation. - - .. versionchanged:: 2.3 - The ``app`` parameter was removed. - - .. versionchanged:: 2.2 - Calls ``current_app.json.dumps``, allowing an app to override - the behavior. - - .. versionchanged:: 2.0.2 - :class:`decimal.Decimal` is supported by converting to a string. - - .. versionchanged:: 2.0 - ``encoding`` will be removed in Flask 2.1. - - .. versionchanged:: 1.0.3 - ``app`` can be passed directly, rather than requiring an app - context for configuration. - """ - if current_app: - return current_app.json.dumps(obj, **kwargs) - - kwargs.setdefault("default", _default) - return _json.dumps(obj, **kwargs) - - -def dump(obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: - """Serialize data as JSON and write to a file. - - If :data:`~flask.current_app` is available, it will use its - :meth:`app.json.dump() ` - method, otherwise it will use :func:`json.dump`. - - :param obj: The data to serialize. - :param fp: A file opened for writing text. Should use the UTF-8 - encoding to be valid JSON. - :param kwargs: Arguments passed to the ``dump`` implementation. - - .. versionchanged:: 2.3 - The ``app`` parameter was removed. - - .. versionchanged:: 2.2 - Calls ``current_app.json.dump``, allowing an app to override - the behavior. - - .. versionchanged:: 2.0 - Writing to a binary file, and the ``encoding`` argument, will be - removed in Flask 2.1. - """ - if current_app: - current_app.json.dump(obj, fp, **kwargs) - else: - kwargs.setdefault("default", _default) - _json.dump(obj, fp, **kwargs) - - -def loads(s: str | bytes, **kwargs: t.Any) -> t.Any: - """Deserialize data as JSON. - - If :data:`~flask.current_app` is available, it will use its - :meth:`app.json.loads() ` - method, otherwise it will use :func:`json.loads`. - - :param s: Text or UTF-8 bytes. - :param kwargs: Arguments passed to the ``loads`` implementation. - - .. versionchanged:: 2.3 - The ``app`` parameter was removed. - - .. versionchanged:: 2.2 - Calls ``current_app.json.loads``, allowing an app to override - the behavior. - - .. versionchanged:: 2.0 - ``encoding`` will be removed in Flask 2.1. The data must be a - string or UTF-8 bytes. - - .. versionchanged:: 1.0.3 - ``app`` can be passed directly, rather than requiring an app - context for configuration. - """ - if current_app: - return current_app.json.loads(s, **kwargs) - - return _json.loads(s, **kwargs) - - -def load(fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: - """Deserialize data as JSON read from a file. - - If :data:`~flask.current_app` is available, it will use its - :meth:`app.json.load() ` - method, otherwise it will use :func:`json.load`. - - :param fp: A file opened for reading text or UTF-8 bytes. - :param kwargs: Arguments passed to the ``load`` implementation. - - .. versionchanged:: 2.3 - The ``app`` parameter was removed. - - .. versionchanged:: 2.2 - Calls ``current_app.json.load``, allowing an app to override - the behavior. - - .. versionchanged:: 2.2 - The ``app`` parameter will be removed in Flask 2.3. - - .. versionchanged:: 2.0 - ``encoding`` will be removed in Flask 2.1. The file must be text - mode, or binary mode with UTF-8 bytes. - """ - if current_app: - return current_app.json.load(fp, **kwargs) - - return _json.load(fp, **kwargs) - - -def jsonify(*args: t.Any, **kwargs: t.Any) -> Response: - """Serialize the given arguments as JSON, and return a - :class:`~flask.Response` object with the ``application/json`` - mimetype. A dict or list returned from a view will be converted to a - JSON response automatically without needing to call this. - - This requires an active request or application context, and calls - :meth:`app.json.response() `. - - In debug mode, the output is formatted with indentation to make it - easier to read. This may also be controlled by the provider. - - Either positional or keyword arguments can be given, not both. - If no arguments are given, ``None`` is serialized. - - :param args: A single value to serialize, or multiple values to - treat as a list to serialize. - :param kwargs: Treat as a dict to serialize. - - .. versionchanged:: 2.2 - Calls ``current_app.json.response``, allowing an app to override - the behavior. - - .. versionchanged:: 2.0.2 - :class:`decimal.Decimal` is supported by converting to a string. - - .. versionchanged:: 0.11 - Added support for serializing top-level arrays. This was a - security risk in ancient browsers. See :ref:`security-json`. - - .. versionadded:: 0.2 - """ - return current_app.json.response(*args, **kwargs) # type: ignore[return-value] diff --git a/serverenv/lib/python3.9/site-packages/flask/json/provider.py b/serverenv/lib/python3.9/site-packages/flask/json/provider.py deleted file mode 100644 index ea7e475..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/json/provider.py +++ /dev/null @@ -1,215 +0,0 @@ -from __future__ import annotations - -import dataclasses -import decimal -import json -import typing as t -import uuid -import weakref -from datetime import date - -from werkzeug.http import http_date - -if t.TYPE_CHECKING: # pragma: no cover - from werkzeug.sansio.response import Response - - from ..sansio.app import App - - -class JSONProvider: - """A standard set of JSON operations for an application. Subclasses - of this can be used to customize JSON behavior or use different - JSON libraries. - - To implement a provider for a specific library, subclass this base - class and implement at least :meth:`dumps` and :meth:`loads`. All - other methods have default implementations. - - To use a different provider, either subclass ``Flask`` and set - :attr:`~flask.Flask.json_provider_class` to a provider class, or set - :attr:`app.json ` to an instance of the class. - - :param app: An application instance. This will be stored as a - :class:`weakref.proxy` on the :attr:`_app` attribute. - - .. versionadded:: 2.2 - """ - - def __init__(self, app: App) -> None: - self._app: App = weakref.proxy(app) - - def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: - """Serialize data as JSON. - - :param obj: The data to serialize. - :param kwargs: May be passed to the underlying JSON library. - """ - raise NotImplementedError - - def dump(self, obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: - """Serialize data as JSON and write to a file. - - :param obj: The data to serialize. - :param fp: A file opened for writing text. Should use the UTF-8 - encoding to be valid JSON. - :param kwargs: May be passed to the underlying JSON library. - """ - fp.write(self.dumps(obj, **kwargs)) - - def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: - """Deserialize data as JSON. - - :param s: Text or UTF-8 bytes. - :param kwargs: May be passed to the underlying JSON library. - """ - raise NotImplementedError - - def load(self, fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: - """Deserialize data as JSON read from a file. - - :param fp: A file opened for reading text or UTF-8 bytes. - :param kwargs: May be passed to the underlying JSON library. - """ - return self.loads(fp.read(), **kwargs) - - def _prepare_response_obj( - self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any] - ) -> t.Any: - if args and kwargs: - raise TypeError("app.json.response() takes either args or kwargs, not both") - - if not args and not kwargs: - return None - - if len(args) == 1: - return args[0] - - return args or kwargs - - def response(self, *args: t.Any, **kwargs: t.Any) -> Response: - """Serialize the given arguments as JSON, and return a - :class:`~flask.Response` object with the ``application/json`` - mimetype. - - The :func:`~flask.json.jsonify` function calls this method for - the current application. - - Either positional or keyword arguments can be given, not both. - If no arguments are given, ``None`` is serialized. - - :param args: A single value to serialize, or multiple values to - treat as a list to serialize. - :param kwargs: Treat as a dict to serialize. - """ - obj = self._prepare_response_obj(args, kwargs) - return self._app.response_class(self.dumps(obj), mimetype="application/json") - - -def _default(o: t.Any) -> t.Any: - if isinstance(o, date): - return http_date(o) - - if isinstance(o, (decimal.Decimal, uuid.UUID)): - return str(o) - - if dataclasses and dataclasses.is_dataclass(o): - return dataclasses.asdict(o) # type: ignore[arg-type] - - if hasattr(o, "__html__"): - return str(o.__html__()) - - raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable") - - -class DefaultJSONProvider(JSONProvider): - """Provide JSON operations using Python's built-in :mod:`json` - library. Serializes the following additional data types: - - - :class:`datetime.datetime` and :class:`datetime.date` are - serialized to :rfc:`822` strings. This is the same as the HTTP - date format. - - :class:`uuid.UUID` is serialized to a string. - - :class:`dataclasses.dataclass` is passed to - :func:`dataclasses.asdict`. - - :class:`~markupsafe.Markup` (or any object with a ``__html__`` - method) will call the ``__html__`` method to get a string. - """ - - default: t.Callable[[t.Any], t.Any] = staticmethod(_default) # type: ignore[assignment] - """Apply this function to any object that :meth:`json.dumps` does - not know how to serialize. It should return a valid JSON type or - raise a ``TypeError``. - """ - - ensure_ascii = True - """Replace non-ASCII characters with escape sequences. This may be - more compatible with some clients, but can be disabled for better - performance and size. - """ - - sort_keys = True - """Sort the keys in any serialized dicts. This may be useful for - some caching situations, but can be disabled for better performance. - When enabled, keys must all be strings, they are not converted - before sorting. - """ - - compact: bool | None = None - """If ``True``, or ``None`` out of debug mode, the :meth:`response` - output will not add indentation, newlines, or spaces. If ``False``, - or ``None`` in debug mode, it will use a non-compact representation. - """ - - mimetype = "application/json" - """The mimetype set in :meth:`response`.""" - - def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: - """Serialize data as JSON to a string. - - Keyword arguments are passed to :func:`json.dumps`. Sets some - parameter defaults from the :attr:`default`, - :attr:`ensure_ascii`, and :attr:`sort_keys` attributes. - - :param obj: The data to serialize. - :param kwargs: Passed to :func:`json.dumps`. - """ - kwargs.setdefault("default", self.default) - kwargs.setdefault("ensure_ascii", self.ensure_ascii) - kwargs.setdefault("sort_keys", self.sort_keys) - return json.dumps(obj, **kwargs) - - def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: - """Deserialize data as JSON from a string or bytes. - - :param s: Text or UTF-8 bytes. - :param kwargs: Passed to :func:`json.loads`. - """ - return json.loads(s, **kwargs) - - def response(self, *args: t.Any, **kwargs: t.Any) -> Response: - """Serialize the given arguments as JSON, and return a - :class:`~flask.Response` object with it. The response mimetype - will be "application/json" and can be changed with - :attr:`mimetype`. - - If :attr:`compact` is ``False`` or debug mode is enabled, the - output will be formatted to be easier to read. - - Either positional or keyword arguments can be given, not both. - If no arguments are given, ``None`` is serialized. - - :param args: A single value to serialize, or multiple values to - treat as a list to serialize. - :param kwargs: Treat as a dict to serialize. - """ - obj = self._prepare_response_obj(args, kwargs) - dump_args: dict[str, t.Any] = {} - - if (self.compact is None and self._app.debug) or self.compact is False: - dump_args.setdefault("indent", 2) - else: - dump_args.setdefault("separators", (",", ":")) - - return self._app.response_class( - f"{self.dumps(obj, **dump_args)}\n", mimetype=self.mimetype - ) diff --git a/serverenv/lib/python3.9/site-packages/flask/json/tag.py b/serverenv/lib/python3.9/site-packages/flask/json/tag.py deleted file mode 100644 index 8dc3629..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/json/tag.py +++ /dev/null @@ -1,327 +0,0 @@ -""" -Tagged JSON -~~~~~~~~~~~ - -A compact representation for lossless serialization of non-standard JSON -types. :class:`~flask.sessions.SecureCookieSessionInterface` uses this -to serialize the session data, but it may be useful in other places. It -can be extended to support other types. - -.. autoclass:: TaggedJSONSerializer - :members: - -.. autoclass:: JSONTag - :members: - -Let's see an example that adds support for -:class:`~collections.OrderedDict`. Dicts don't have an order in JSON, so -to handle this we will dump the items as a list of ``[key, value]`` -pairs. Subclass :class:`JSONTag` and give it the new key ``' od'`` to -identify the type. The session serializer processes dicts first, so -insert the new tag at the front of the order since ``OrderedDict`` must -be processed before ``dict``. - -.. code-block:: python - - from flask.json.tag import JSONTag - - class TagOrderedDict(JSONTag): - __slots__ = ('serializer',) - key = ' od' - - def check(self, value): - return isinstance(value, OrderedDict) - - def to_json(self, value): - return [[k, self.serializer.tag(v)] for k, v in iteritems(value)] - - def to_python(self, value): - return OrderedDict(value) - - app.session_interface.serializer.register(TagOrderedDict, index=0) -""" - -from __future__ import annotations - -import typing as t -from base64 import b64decode -from base64 import b64encode -from datetime import datetime -from uuid import UUID - -from markupsafe import Markup -from werkzeug.http import http_date -from werkzeug.http import parse_date - -from ..json import dumps -from ..json import loads - - -class JSONTag: - """Base class for defining type tags for :class:`TaggedJSONSerializer`.""" - - __slots__ = ("serializer",) - - #: The tag to mark the serialized object with. If empty, this tag is - #: only used as an intermediate step during tagging. - key: str = "" - - def __init__(self, serializer: TaggedJSONSerializer) -> None: - """Create a tagger for the given serializer.""" - self.serializer = serializer - - def check(self, value: t.Any) -> bool: - """Check if the given value should be tagged by this tag.""" - raise NotImplementedError - - def to_json(self, value: t.Any) -> t.Any: - """Convert the Python object to an object that is a valid JSON type. - The tag will be added later.""" - raise NotImplementedError - - def to_python(self, value: t.Any) -> t.Any: - """Convert the JSON representation back to the correct type. The tag - will already be removed.""" - raise NotImplementedError - - def tag(self, value: t.Any) -> dict[str, t.Any]: - """Convert the value to a valid JSON type and add the tag structure - around it.""" - return {self.key: self.to_json(value)} - - -class TagDict(JSONTag): - """Tag for 1-item dicts whose only key matches a registered tag. - - Internally, the dict key is suffixed with `__`, and the suffix is removed - when deserializing. - """ - - __slots__ = () - key = " di" - - def check(self, value: t.Any) -> bool: - return ( - isinstance(value, dict) - and len(value) == 1 - and next(iter(value)) in self.serializer.tags - ) - - def to_json(self, value: t.Any) -> t.Any: - key = next(iter(value)) - return {f"{key}__": self.serializer.tag(value[key])} - - def to_python(self, value: t.Any) -> t.Any: - key = next(iter(value)) - return {key[:-2]: value[key]} - - -class PassDict(JSONTag): - __slots__ = () - - def check(self, value: t.Any) -> bool: - return isinstance(value, dict) - - def to_json(self, value: t.Any) -> t.Any: - # JSON objects may only have string keys, so don't bother tagging the - # key here. - return {k: self.serializer.tag(v) for k, v in value.items()} - - tag = to_json - - -class TagTuple(JSONTag): - __slots__ = () - key = " t" - - def check(self, value: t.Any) -> bool: - return isinstance(value, tuple) - - def to_json(self, value: t.Any) -> t.Any: - return [self.serializer.tag(item) for item in value] - - def to_python(self, value: t.Any) -> t.Any: - return tuple(value) - - -class PassList(JSONTag): - __slots__ = () - - def check(self, value: t.Any) -> bool: - return isinstance(value, list) - - def to_json(self, value: t.Any) -> t.Any: - return [self.serializer.tag(item) for item in value] - - tag = to_json - - -class TagBytes(JSONTag): - __slots__ = () - key = " b" - - def check(self, value: t.Any) -> bool: - return isinstance(value, bytes) - - def to_json(self, value: t.Any) -> t.Any: - return b64encode(value).decode("ascii") - - def to_python(self, value: t.Any) -> t.Any: - return b64decode(value) - - -class TagMarkup(JSONTag): - """Serialize anything matching the :class:`~markupsafe.Markup` API by - having a ``__html__`` method to the result of that method. Always - deserializes to an instance of :class:`~markupsafe.Markup`.""" - - __slots__ = () - key = " m" - - def check(self, value: t.Any) -> bool: - return callable(getattr(value, "__html__", None)) - - def to_json(self, value: t.Any) -> t.Any: - return str(value.__html__()) - - def to_python(self, value: t.Any) -> t.Any: - return Markup(value) - - -class TagUUID(JSONTag): - __slots__ = () - key = " u" - - def check(self, value: t.Any) -> bool: - return isinstance(value, UUID) - - def to_json(self, value: t.Any) -> t.Any: - return value.hex - - def to_python(self, value: t.Any) -> t.Any: - return UUID(value) - - -class TagDateTime(JSONTag): - __slots__ = () - key = " d" - - def check(self, value: t.Any) -> bool: - return isinstance(value, datetime) - - def to_json(self, value: t.Any) -> t.Any: - return http_date(value) - - def to_python(self, value: t.Any) -> t.Any: - return parse_date(value) - - -class TaggedJSONSerializer: - """Serializer that uses a tag system to compactly represent objects that - are not JSON types. Passed as the intermediate serializer to - :class:`itsdangerous.Serializer`. - - The following extra types are supported: - - * :class:`dict` - * :class:`tuple` - * :class:`bytes` - * :class:`~markupsafe.Markup` - * :class:`~uuid.UUID` - * :class:`~datetime.datetime` - """ - - __slots__ = ("tags", "order") - - #: Tag classes to bind when creating the serializer. Other tags can be - #: added later using :meth:`~register`. - default_tags = [ - TagDict, - PassDict, - TagTuple, - PassList, - TagBytes, - TagMarkup, - TagUUID, - TagDateTime, - ] - - def __init__(self) -> None: - self.tags: dict[str, JSONTag] = {} - self.order: list[JSONTag] = [] - - for cls in self.default_tags: - self.register(cls) - - def register( - self, - tag_class: type[JSONTag], - force: bool = False, - index: int | None = None, - ) -> None: - """Register a new tag with this serializer. - - :param tag_class: tag class to register. Will be instantiated with this - serializer instance. - :param force: overwrite an existing tag. If false (default), a - :exc:`KeyError` is raised. - :param index: index to insert the new tag in the tag order. Useful when - the new tag is a special case of an existing tag. If ``None`` - (default), the tag is appended to the end of the order. - - :raise KeyError: if the tag key is already registered and ``force`` is - not true. - """ - tag = tag_class(self) - key = tag.key - - if key: - if not force and key in self.tags: - raise KeyError(f"Tag '{key}' is already registered.") - - self.tags[key] = tag - - if index is None: - self.order.append(tag) - else: - self.order.insert(index, tag) - - def tag(self, value: t.Any) -> t.Any: - """Convert a value to a tagged representation if necessary.""" - for tag in self.order: - if tag.check(value): - return tag.tag(value) - - return value - - def untag(self, value: dict[str, t.Any]) -> t.Any: - """Convert a tagged representation back to the original type.""" - if len(value) != 1: - return value - - key = next(iter(value)) - - if key not in self.tags: - return value - - return self.tags[key].to_python(value[key]) - - def _untag_scan(self, value: t.Any) -> t.Any: - if isinstance(value, dict): - # untag each item recursively - value = {k: self._untag_scan(v) for k, v in value.items()} - # untag the dict itself - value = self.untag(value) - elif isinstance(value, list): - # untag each item recursively - value = [self._untag_scan(item) for item in value] - - return value - - def dumps(self, value: t.Any) -> str: - """Tag the value and dump it to a compact JSON string.""" - return dumps(self.tag(value), separators=(",", ":")) - - def loads(self, value: str) -> t.Any: - """Load data from a JSON string and deserialized any tagged objects.""" - return self._untag_scan(loads(value)) diff --git a/serverenv/lib/python3.9/site-packages/flask/logging.py b/serverenv/lib/python3.9/site-packages/flask/logging.py deleted file mode 100644 index 0cb8f43..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/logging.py +++ /dev/null @@ -1,79 +0,0 @@ -from __future__ import annotations - -import logging -import sys -import typing as t - -from werkzeug.local import LocalProxy - -from .globals import request - -if t.TYPE_CHECKING: # pragma: no cover - from .sansio.app import App - - -@LocalProxy -def wsgi_errors_stream() -> t.TextIO: - """Find the most appropriate error stream for the application. If a request - is active, log to ``wsgi.errors``, otherwise use ``sys.stderr``. - - If you configure your own :class:`logging.StreamHandler`, you may want to - use this for the stream. If you are using file or dict configuration and - can't import this directly, you can refer to it as - ``ext://flask.logging.wsgi_errors_stream``. - """ - if request: - return request.environ["wsgi.errors"] # type: ignore[no-any-return] - - return sys.stderr - - -def has_level_handler(logger: logging.Logger) -> bool: - """Check if there is a handler in the logging chain that will handle the - given logger's :meth:`effective level <~logging.Logger.getEffectiveLevel>`. - """ - level = logger.getEffectiveLevel() - current = logger - - while current: - if any(handler.level <= level for handler in current.handlers): - return True - - if not current.propagate: - break - - current = current.parent # type: ignore - - return False - - -#: Log messages to :func:`~flask.logging.wsgi_errors_stream` with the format -#: ``[%(asctime)s] %(levelname)s in %(module)s: %(message)s``. -default_handler = logging.StreamHandler(wsgi_errors_stream) # type: ignore -default_handler.setFormatter( - logging.Formatter("[%(asctime)s] %(levelname)s in %(module)s: %(message)s") -) - - -def create_logger(app: App) -> logging.Logger: - """Get the Flask app's logger and configure it if needed. - - The logger name will be the same as - :attr:`app.import_name `. - - When :attr:`~flask.Flask.debug` is enabled, set the logger level to - :data:`logging.DEBUG` if it is not set. - - If there is no handler for the logger's effective level, add a - :class:`~logging.StreamHandler` for - :func:`~flask.logging.wsgi_errors_stream` with a basic format. - """ - logger = logging.getLogger(app.name) - - if app.debug and not logger.level: - logger.setLevel(logging.DEBUG) - - if not has_level_handler(logger): - logger.addHandler(default_handler) - - return logger diff --git a/serverenv/lib/python3.9/site-packages/flask/py.typed b/serverenv/lib/python3.9/site-packages/flask/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/flask/sansio/README.md b/serverenv/lib/python3.9/site-packages/flask/sansio/README.md deleted file mode 100644 index 623ac19..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/sansio/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Sansio - -This folder contains code that can be used by alternative Flask -implementations, for example Quart. The code therefore cannot do any -IO, nor be part of a likely IO path. Finally this code cannot use the -Flask globals. diff --git a/serverenv/lib/python3.9/site-packages/flask/sansio/app.py b/serverenv/lib/python3.9/site-packages/flask/sansio/app.py deleted file mode 100644 index 3620171..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/sansio/app.py +++ /dev/null @@ -1,964 +0,0 @@ -from __future__ import annotations - -import logging -import os -import sys -import typing as t -from datetime import timedelta -from itertools import chain - -from werkzeug.exceptions import Aborter -from werkzeug.exceptions import BadRequest -from werkzeug.exceptions import BadRequestKeyError -from werkzeug.routing import BuildError -from werkzeug.routing import Map -from werkzeug.routing import Rule -from werkzeug.sansio.response import Response -from werkzeug.utils import cached_property -from werkzeug.utils import redirect as _wz_redirect - -from .. import typing as ft -from ..config import Config -from ..config import ConfigAttribute -from ..ctx import _AppCtxGlobals -from ..helpers import _split_blueprint_path -from ..helpers import get_debug_flag -from ..json.provider import DefaultJSONProvider -from ..json.provider import JSONProvider -from ..logging import create_logger -from ..templating import DispatchingJinjaLoader -from ..templating import Environment -from .scaffold import _endpoint_from_view_func -from .scaffold import find_package -from .scaffold import Scaffold -from .scaffold import setupmethod - -if t.TYPE_CHECKING: # pragma: no cover - from werkzeug.wrappers import Response as BaseResponse - - from ..testing import FlaskClient - from ..testing import FlaskCliRunner - from .blueprints import Blueprint - -T_shell_context_processor = t.TypeVar( - "T_shell_context_processor", bound=ft.ShellContextProcessorCallable -) -T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) -T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) -T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) -T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) - - -def _make_timedelta(value: timedelta | int | None) -> timedelta | None: - if value is None or isinstance(value, timedelta): - return value - - return timedelta(seconds=value) - - -class App(Scaffold): - """The flask object implements a WSGI application and acts as the central - object. It is passed the name of the module or package of the - application. Once it is created it will act as a central registry for - the view functions, the URL rules, template configuration and much more. - - The name of the package is used to resolve resources from inside the - package or the folder the module is contained in depending on if the - package parameter resolves to an actual python package (a folder with - an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). - - For more information about resource loading, see :func:`open_resource`. - - Usually you create a :class:`Flask` instance in your main module or - in the :file:`__init__.py` file of your package like this:: - - from flask import Flask - app = Flask(__name__) - - .. admonition:: About the First Parameter - - The idea of the first parameter is to give Flask an idea of what - belongs to your application. This name is used to find resources - on the filesystem, can be used by extensions to improve debugging - information and a lot more. - - So it's important what you provide there. If you are using a single - module, `__name__` is always the correct value. If you however are - using a package, it's usually recommended to hardcode the name of - your package there. - - For example if your application is defined in :file:`yourapplication/app.py` - you should create it with one of the two versions below:: - - app = Flask('yourapplication') - app = Flask(__name__.split('.')[0]) - - Why is that? The application will work even with `__name__`, thanks - to how resources are looked up. However it will make debugging more - painful. Certain extensions can make assumptions based on the - import name of your application. For example the Flask-SQLAlchemy - extension will look for the code in your application that triggered - an SQL query in debug mode. If the import name is not properly set - up, that debugging information is lost. (For example it would only - pick up SQL queries in `yourapplication.app` and not - `yourapplication.views.frontend`) - - .. versionadded:: 0.7 - The `static_url_path`, `static_folder`, and `template_folder` - parameters were added. - - .. versionadded:: 0.8 - The `instance_path` and `instance_relative_config` parameters were - added. - - .. versionadded:: 0.11 - The `root_path` parameter was added. - - .. versionadded:: 1.0 - The ``host_matching`` and ``static_host`` parameters were added. - - .. versionadded:: 1.0 - The ``subdomain_matching`` parameter was added. Subdomain - matching needs to be enabled manually now. Setting - :data:`SERVER_NAME` does not implicitly enable it. - - :param import_name: the name of the application package - :param static_url_path: can be used to specify a different path for the - static files on the web. Defaults to the name - of the `static_folder` folder. - :param static_folder: The folder with static files that is served at - ``static_url_path``. Relative to the application ``root_path`` - or an absolute path. Defaults to ``'static'``. - :param static_host: the host to use when adding the static route. - Defaults to None. Required when using ``host_matching=True`` - with a ``static_folder`` configured. - :param host_matching: set ``url_map.host_matching`` attribute. - Defaults to False. - :param subdomain_matching: consider the subdomain relative to - :data:`SERVER_NAME` when matching routes. Defaults to False. - :param template_folder: the folder that contains the templates that should - be used by the application. Defaults to - ``'templates'`` folder in the root path of the - application. - :param instance_path: An alternative instance path for the application. - By default the folder ``'instance'`` next to the - package or module is assumed to be the instance - path. - :param instance_relative_config: if set to ``True`` relative filenames - for loading the config are assumed to - be relative to the instance path instead - of the application root. - :param root_path: The path to the root of the application files. - This should only be set manually when it can't be detected - automatically, such as for namespace packages. - """ - - #: The class of the object assigned to :attr:`aborter`, created by - #: :meth:`create_aborter`. That object is called by - #: :func:`flask.abort` to raise HTTP errors, and can be - #: called directly as well. - #: - #: Defaults to :class:`werkzeug.exceptions.Aborter`. - #: - #: .. versionadded:: 2.2 - aborter_class = Aborter - - #: The class that is used for the Jinja environment. - #: - #: .. versionadded:: 0.11 - jinja_environment = Environment - - #: The class that is used for the :data:`~flask.g` instance. - #: - #: Example use cases for a custom class: - #: - #: 1. Store arbitrary attributes on flask.g. - #: 2. Add a property for lazy per-request database connectors. - #: 3. Return None instead of AttributeError on unexpected attributes. - #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. - #: - #: In Flask 0.9 this property was called `request_globals_class` but it - #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the - #: flask.g object is now application context scoped. - #: - #: .. versionadded:: 0.10 - app_ctx_globals_class = _AppCtxGlobals - - #: The class that is used for the ``config`` attribute of this app. - #: Defaults to :class:`~flask.Config`. - #: - #: Example use cases for a custom class: - #: - #: 1. Default values for certain config options. - #: 2. Access to config values through attributes in addition to keys. - #: - #: .. versionadded:: 0.11 - config_class = Config - - #: The testing flag. Set this to ``True`` to enable the test mode of - #: Flask extensions (and in the future probably also Flask itself). - #: For example this might activate test helpers that have an - #: additional runtime cost which should not be enabled by default. - #: - #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the - #: default it's implicitly enabled. - #: - #: This attribute can also be configured from the config with the - #: ``TESTING`` configuration key. Defaults to ``False``. - testing = ConfigAttribute[bool]("TESTING") - - #: If a secret key is set, cryptographic components can use this to - #: sign cookies and other things. Set this to a complex random value - #: when you want to use the secure cookie for instance. - #: - #: This attribute can also be configured from the config with the - #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. - secret_key = ConfigAttribute[t.Union[str, bytes, None]]("SECRET_KEY") - - #: A :class:`~datetime.timedelta` which is used to set the expiration - #: date of a permanent session. The default is 31 days which makes a - #: permanent session survive for roughly one month. - #: - #: This attribute can also be configured from the config with the - #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to - #: ``timedelta(days=31)`` - permanent_session_lifetime = ConfigAttribute[timedelta]( - "PERMANENT_SESSION_LIFETIME", - get_converter=_make_timedelta, # type: ignore[arg-type] - ) - - json_provider_class: type[JSONProvider] = DefaultJSONProvider - """A subclass of :class:`~flask.json.provider.JSONProvider`. An - instance is created and assigned to :attr:`app.json` when creating - the app. - - The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses - Python's built-in :mod:`json` library. A different provider can use - a different JSON library. - - .. versionadded:: 2.2 - """ - - #: Options that are passed to the Jinja environment in - #: :meth:`create_jinja_environment`. Changing these options after - #: the environment is created (accessing :attr:`jinja_env`) will - #: have no effect. - #: - #: .. versionchanged:: 1.1.0 - #: This is a ``dict`` instead of an ``ImmutableDict`` to allow - #: easier configuration. - #: - jinja_options: dict[str, t.Any] = {} - - #: The rule object to use for URL rules created. This is used by - #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. - #: - #: .. versionadded:: 0.7 - url_rule_class = Rule - - #: The map object to use for storing the URL rules and routing - #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. - #: - #: .. versionadded:: 1.1.0 - url_map_class = Map - - #: The :meth:`test_client` method creates an instance of this test - #: client class. Defaults to :class:`~flask.testing.FlaskClient`. - #: - #: .. versionadded:: 0.7 - test_client_class: type[FlaskClient] | None = None - - #: The :class:`~click.testing.CliRunner` subclass, by default - #: :class:`~flask.testing.FlaskCliRunner` that is used by - #: :meth:`test_cli_runner`. Its ``__init__`` method should take a - #: Flask app object as the first argument. - #: - #: .. versionadded:: 1.0 - test_cli_runner_class: type[FlaskCliRunner] | None = None - - default_config: dict[str, t.Any] - response_class: type[Response] - - def __init__( - self, - import_name: str, - static_url_path: str | None = None, - static_folder: str | os.PathLike[str] | None = "static", - static_host: str | None = None, - host_matching: bool = False, - subdomain_matching: bool = False, - template_folder: str | os.PathLike[str] | None = "templates", - instance_path: str | None = None, - instance_relative_config: bool = False, - root_path: str | None = None, - ) -> None: - super().__init__( - import_name=import_name, - static_folder=static_folder, - static_url_path=static_url_path, - template_folder=template_folder, - root_path=root_path, - ) - - if instance_path is None: - instance_path = self.auto_find_instance_path() - elif not os.path.isabs(instance_path): - raise ValueError( - "If an instance path is provided it must be absolute." - " A relative path was given instead." - ) - - #: Holds the path to the instance folder. - #: - #: .. versionadded:: 0.8 - self.instance_path = instance_path - - #: The configuration dictionary as :class:`Config`. This behaves - #: exactly like a regular dictionary but supports additional methods - #: to load a config from files. - self.config = self.make_config(instance_relative_config) - - #: An instance of :attr:`aborter_class` created by - #: :meth:`make_aborter`. This is called by :func:`flask.abort` - #: to raise HTTP errors, and can be called directly as well. - #: - #: .. versionadded:: 2.2 - #: Moved from ``flask.abort``, which calls this object. - self.aborter = self.make_aborter() - - self.json: JSONProvider = self.json_provider_class(self) - """Provides access to JSON methods. Functions in ``flask.json`` - will call methods on this provider when the application context - is active. Used for handling JSON requests and responses. - - An instance of :attr:`json_provider_class`. Can be customized by - changing that attribute on a subclass, or by assigning to this - attribute afterwards. - - The default, :class:`~flask.json.provider.DefaultJSONProvider`, - uses Python's built-in :mod:`json` library. A different provider - can use a different JSON library. - - .. versionadded:: 2.2 - """ - - #: A list of functions that are called by - #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a - #: :exc:`~werkzeug.routing.BuildError`. Each function is called - #: with ``error``, ``endpoint`` and ``values``. If a function - #: returns ``None`` or raises a ``BuildError``, it is skipped. - #: Otherwise, its return value is returned by ``url_for``. - #: - #: .. versionadded:: 0.9 - self.url_build_error_handlers: list[ - t.Callable[[Exception, str, dict[str, t.Any]], str] - ] = [] - - #: A list of functions that are called when the application context - #: is destroyed. Since the application context is also torn down - #: if the request ends this is the place to store code that disconnects - #: from databases. - #: - #: .. versionadded:: 0.9 - self.teardown_appcontext_funcs: list[ft.TeardownCallable] = [] - - #: A list of shell context processor functions that should be run - #: when a shell context is created. - #: - #: .. versionadded:: 0.11 - self.shell_context_processors: list[ft.ShellContextProcessorCallable] = [] - - #: Maps registered blueprint names to blueprint objects. The - #: dict retains the order the blueprints were registered in. - #: Blueprints can be registered multiple times, this dict does - #: not track how often they were attached. - #: - #: .. versionadded:: 0.7 - self.blueprints: dict[str, Blueprint] = {} - - #: a place where extensions can store application specific state. For - #: example this is where an extension could store database engines and - #: similar things. - #: - #: The key must match the name of the extension module. For example in - #: case of a "Flask-Foo" extension in `flask_foo`, the key would be - #: ``'foo'``. - #: - #: .. versionadded:: 0.7 - self.extensions: dict[str, t.Any] = {} - - #: The :class:`~werkzeug.routing.Map` for this instance. You can use - #: this to change the routing converters after the class was created - #: but before any routes are connected. Example:: - #: - #: from werkzeug.routing import BaseConverter - #: - #: class ListConverter(BaseConverter): - #: def to_python(self, value): - #: return value.split(',') - #: def to_url(self, values): - #: return ','.join(super(ListConverter, self).to_url(value) - #: for value in values) - #: - #: app = Flask(__name__) - #: app.url_map.converters['list'] = ListConverter - self.url_map = self.url_map_class(host_matching=host_matching) - - self.subdomain_matching = subdomain_matching - - # tracks internally if the application already handled at least one - # request. - self._got_first_request = False - - def _check_setup_finished(self, f_name: str) -> None: - if self._got_first_request: - raise AssertionError( - f"The setup method '{f_name}' can no longer be called" - " on the application. It has already handled its first" - " request, any changes will not be applied" - " consistently.\n" - "Make sure all imports, decorators, functions, etc." - " needed to set up the application are done before" - " running it." - ) - - @cached_property - def name(self) -> str: # type: ignore - """The name of the application. This is usually the import name - with the difference that it's guessed from the run file if the - import name is main. This name is used as a display name when - Flask needs the name of the application. It can be set and overridden - to change the value. - - .. versionadded:: 0.8 - """ - if self.import_name == "__main__": - fn: str | None = getattr(sys.modules["__main__"], "__file__", None) - if fn is None: - return "__main__" - return os.path.splitext(os.path.basename(fn))[0] - return self.import_name - - @cached_property - def logger(self) -> logging.Logger: - """A standard Python :class:`~logging.Logger` for the app, with - the same name as :attr:`name`. - - In debug mode, the logger's :attr:`~logging.Logger.level` will - be set to :data:`~logging.DEBUG`. - - If there are no handlers configured, a default handler will be - added. See :doc:`/logging` for more information. - - .. versionchanged:: 1.1.0 - The logger takes the same name as :attr:`name` rather than - hard-coding ``"flask.app"``. - - .. versionchanged:: 1.0.0 - Behavior was simplified. The logger is always named - ``"flask.app"``. The level is only set during configuration, - it doesn't check ``app.debug`` each time. Only one format is - used, not different ones depending on ``app.debug``. No - handlers are removed, and a handler is only added if no - handlers are already configured. - - .. versionadded:: 0.3 - """ - return create_logger(self) - - @cached_property - def jinja_env(self) -> Environment: - """The Jinja environment used to load templates. - - The environment is created the first time this property is - accessed. Changing :attr:`jinja_options` after that will have no - effect. - """ - return self.create_jinja_environment() - - def create_jinja_environment(self) -> Environment: - raise NotImplementedError() - - def make_config(self, instance_relative: bool = False) -> Config: - """Used to create the config attribute by the Flask constructor. - The `instance_relative` parameter is passed in from the constructor - of Flask (there named `instance_relative_config`) and indicates if - the config should be relative to the instance path or the root path - of the application. - - .. versionadded:: 0.8 - """ - root_path = self.root_path - if instance_relative: - root_path = self.instance_path - defaults = dict(self.default_config) - defaults["DEBUG"] = get_debug_flag() - return self.config_class(root_path, defaults) - - def make_aborter(self) -> Aborter: - """Create the object to assign to :attr:`aborter`. That object - is called by :func:`flask.abort` to raise HTTP errors, and can - be called directly as well. - - By default, this creates an instance of :attr:`aborter_class`, - which defaults to :class:`werkzeug.exceptions.Aborter`. - - .. versionadded:: 2.2 - """ - return self.aborter_class() - - def auto_find_instance_path(self) -> str: - """Tries to locate the instance path if it was not provided to the - constructor of the application class. It will basically calculate - the path to a folder named ``instance`` next to your main file or - the package. - - .. versionadded:: 0.8 - """ - prefix, package_path = find_package(self.import_name) - if prefix is None: - return os.path.join(package_path, "instance") - return os.path.join(prefix, "var", f"{self.name}-instance") - - def create_global_jinja_loader(self) -> DispatchingJinjaLoader: - """Creates the loader for the Jinja2 environment. Can be used to - override just the loader and keeping the rest unchanged. It's - discouraged to override this function. Instead one should override - the :meth:`jinja_loader` function instead. - - The global loader dispatches between the loaders of the application - and the individual blueprints. - - .. versionadded:: 0.7 - """ - return DispatchingJinjaLoader(self) - - def select_jinja_autoescape(self, filename: str) -> bool: - """Returns ``True`` if autoescaping should be active for the given - template name. If no template name is given, returns `True`. - - .. versionchanged:: 2.2 - Autoescaping is now enabled by default for ``.svg`` files. - - .. versionadded:: 0.5 - """ - if filename is None: - return True - return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg")) - - @property - def debug(self) -> bool: - """Whether debug mode is enabled. When using ``flask run`` to start the - development server, an interactive debugger will be shown for unhandled - exceptions, and the server will be reloaded when code changes. This maps to the - :data:`DEBUG` config key. It may not behave as expected if set late. - - **Do not enable debug mode when deploying in production.** - - Default: ``False`` - """ - return self.config["DEBUG"] # type: ignore[no-any-return] - - @debug.setter - def debug(self, value: bool) -> None: - self.config["DEBUG"] = value - - if self.config["TEMPLATES_AUTO_RELOAD"] is None: - self.jinja_env.auto_reload = value - - @setupmethod - def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: - """Register a :class:`~flask.Blueprint` on the application. Keyword - arguments passed to this method will override the defaults set on the - blueprint. - - Calls the blueprint's :meth:`~flask.Blueprint.register` method after - recording the blueprint in the application's :attr:`blueprints`. - - :param blueprint: The blueprint to register. - :param url_prefix: Blueprint routes will be prefixed with this. - :param subdomain: Blueprint routes will match on this subdomain. - :param url_defaults: Blueprint routes will use these default values for - view arguments. - :param options: Additional keyword arguments are passed to - :class:`~flask.blueprints.BlueprintSetupState`. They can be - accessed in :meth:`~flask.Blueprint.record` callbacks. - - .. versionchanged:: 2.0.1 - The ``name`` option can be used to change the (pre-dotted) - name the blueprint is registered with. This allows the same - blueprint to be registered multiple times with unique names - for ``url_for``. - - .. versionadded:: 0.7 - """ - blueprint.register(self, options) - - def iter_blueprints(self) -> t.ValuesView[Blueprint]: - """Iterates over all blueprints by the order they were registered. - - .. versionadded:: 0.11 - """ - return self.blueprints.values() - - @setupmethod - def add_url_rule( - self, - rule: str, - endpoint: str | None = None, - view_func: ft.RouteCallable | None = None, - provide_automatic_options: bool | None = None, - **options: t.Any, - ) -> None: - if endpoint is None: - endpoint = _endpoint_from_view_func(view_func) # type: ignore - options["endpoint"] = endpoint - methods = options.pop("methods", None) - - # if the methods are not given and the view_func object knows its - # methods we can use that instead. If neither exists, we go with - # a tuple of only ``GET`` as default. - if methods is None: - methods = getattr(view_func, "methods", None) or ("GET",) - if isinstance(methods, str): - raise TypeError( - "Allowed methods must be a list of strings, for" - ' example: @app.route(..., methods=["POST"])' - ) - methods = {item.upper() for item in methods} - - # Methods that should always be added - required_methods: set[str] = set(getattr(view_func, "required_methods", ())) - - # starting with Flask 0.8 the view_func object can disable and - # force-enable the automatic options handling. - if provide_automatic_options is None: - provide_automatic_options = getattr( - view_func, "provide_automatic_options", None - ) - - if provide_automatic_options is None: - if "OPTIONS" not in methods and self.config["PROVIDE_AUTOMATIC_OPTIONS"]: - provide_automatic_options = True - required_methods.add("OPTIONS") - else: - provide_automatic_options = False - - # Add the required methods now. - methods |= required_methods - - rule_obj = self.url_rule_class(rule, methods=methods, **options) - rule_obj.provide_automatic_options = provide_automatic_options # type: ignore[attr-defined] - - self.url_map.add(rule_obj) - if view_func is not None: - old_func = self.view_functions.get(endpoint) - if old_func is not None and old_func != view_func: - raise AssertionError( - "View function mapping is overwriting an existing" - f" endpoint function: {endpoint}" - ) - self.view_functions[endpoint] = view_func - - @setupmethod - def template_filter( - self, name: str | None = None - ) -> t.Callable[[T_template_filter], T_template_filter]: - """A decorator that is used to register custom template filter. - You can specify a name for the filter, otherwise the function - name will be used. Example:: - - @app.template_filter() - def reverse(s): - return s[::-1] - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - - def decorator(f: T_template_filter) -> T_template_filter: - self.add_template_filter(f, name=name) - return f - - return decorator - - @setupmethod - def add_template_filter( - self, f: ft.TemplateFilterCallable, name: str | None = None - ) -> None: - """Register a custom template filter. Works exactly like the - :meth:`template_filter` decorator. - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - self.jinja_env.filters[name or f.__name__] = f - - @setupmethod - def template_test( - self, name: str | None = None - ) -> t.Callable[[T_template_test], T_template_test]: - """A decorator that is used to register custom template test. - You can specify a name for the test, otherwise the function - name will be used. Example:: - - @app.template_test() - def is_prime(n): - if n == 2: - return True - for i in range(2, int(math.ceil(math.sqrt(n))) + 1): - if n % i == 0: - return False - return True - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - - def decorator(f: T_template_test) -> T_template_test: - self.add_template_test(f, name=name) - return f - - return decorator - - @setupmethod - def add_template_test( - self, f: ft.TemplateTestCallable, name: str | None = None - ) -> None: - """Register a custom template test. Works exactly like the - :meth:`template_test` decorator. - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - self.jinja_env.tests[name or f.__name__] = f - - @setupmethod - def template_global( - self, name: str | None = None - ) -> t.Callable[[T_template_global], T_template_global]: - """A decorator that is used to register a custom template global function. - You can specify a name for the global function, otherwise the function - name will be used. Example:: - - @app.template_global() - def double(n): - return 2 * n - - .. versionadded:: 0.10 - - :param name: the optional name of the global function, otherwise the - function name will be used. - """ - - def decorator(f: T_template_global) -> T_template_global: - self.add_template_global(f, name=name) - return f - - return decorator - - @setupmethod - def add_template_global( - self, f: ft.TemplateGlobalCallable, name: str | None = None - ) -> None: - """Register a custom template global function. Works exactly like the - :meth:`template_global` decorator. - - .. versionadded:: 0.10 - - :param name: the optional name of the global function, otherwise the - function name will be used. - """ - self.jinja_env.globals[name or f.__name__] = f - - @setupmethod - def teardown_appcontext(self, f: T_teardown) -> T_teardown: - """Registers a function to be called when the application - context is popped. The application context is typically popped - after the request context for each request, at the end of CLI - commands, or after a manually pushed context ends. - - .. code-block:: python - - with app.app_context(): - ... - - When the ``with`` block exits (or ``ctx.pop()`` is called), the - teardown functions are called just before the app context is - made inactive. Since a request context typically also manages an - application context it would also be called when you pop a - request context. - - When a teardown function was called because of an unhandled - exception it will be passed an error object. If an - :meth:`errorhandler` is registered, it will handle the exception - and the teardown will not receive it. - - Teardown functions must avoid raising exceptions. If they - execute code that might fail they must surround that code with a - ``try``/``except`` block and log any errors. - - The return values of teardown functions are ignored. - - .. versionadded:: 0.9 - """ - self.teardown_appcontext_funcs.append(f) - return f - - @setupmethod - def shell_context_processor( - self, f: T_shell_context_processor - ) -> T_shell_context_processor: - """Registers a shell context processor function. - - .. versionadded:: 0.11 - """ - self.shell_context_processors.append(f) - return f - - def _find_error_handler( - self, e: Exception, blueprints: list[str] - ) -> ft.ErrorHandlerCallable | None: - """Return a registered error handler for an exception in this order: - blueprint handler for a specific code, app handler for a specific code, - blueprint handler for an exception class, app handler for an exception - class, or ``None`` if a suitable handler is not found. - """ - exc_class, code = self._get_exc_class_and_code(type(e)) - names = (*blueprints, None) - - for c in (code, None) if code is not None else (None,): - for name in names: - handler_map = self.error_handler_spec[name][c] - - if not handler_map: - continue - - for cls in exc_class.__mro__: - handler = handler_map.get(cls) - - if handler is not None: - return handler - return None - - def trap_http_exception(self, e: Exception) -> bool: - """Checks if an HTTP exception should be trapped or not. By default - this will return ``False`` for all exceptions except for a bad request - key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It - also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. - - This is called for all HTTP exceptions raised by a view function. - If it returns ``True`` for any exception the error handler for this - exception is not called and it shows up as regular exception in the - traceback. This is helpful for debugging implicitly raised HTTP - exceptions. - - .. versionchanged:: 1.0 - Bad request errors are not trapped by default in debug mode. - - .. versionadded:: 0.8 - """ - if self.config["TRAP_HTTP_EXCEPTIONS"]: - return True - - trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] - - # if unset, trap key errors in debug mode - if ( - trap_bad_request is None - and self.debug - and isinstance(e, BadRequestKeyError) - ): - return True - - if trap_bad_request: - return isinstance(e, BadRequest) - - return False - - def should_ignore_error(self, error: BaseException | None) -> bool: - """This is called to figure out if an error should be ignored - or not as far as the teardown system is concerned. If this - function returns ``True`` then the teardown handlers will not be - passed the error. - - .. versionadded:: 0.10 - """ - return False - - def redirect(self, location: str, code: int = 302) -> BaseResponse: - """Create a redirect response object. - - This is called by :func:`flask.redirect`, and can be called - directly as well. - - :param location: The URL to redirect to. - :param code: The status code for the redirect. - - .. versionadded:: 2.2 - Moved from ``flask.redirect``, which calls this method. - """ - return _wz_redirect( - location, - code=code, - Response=self.response_class, # type: ignore[arg-type] - ) - - def inject_url_defaults(self, endpoint: str, values: dict[str, t.Any]) -> None: - """Injects the URL defaults for the given endpoint directly into - the values dictionary passed. This is used internally and - automatically called on URL building. - - .. versionadded:: 0.7 - """ - names: t.Iterable[str | None] = (None,) - - # url_for may be called outside a request context, parse the - # passed endpoint instead of using request.blueprints. - if "." in endpoint: - names = chain( - names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0])) - ) - - for name in names: - if name in self.url_default_functions: - for func in self.url_default_functions[name]: - func(endpoint, values) - - def handle_url_build_error( - self, error: BuildError, endpoint: str, values: dict[str, t.Any] - ) -> str: - """Called by :meth:`.url_for` if a - :exc:`~werkzeug.routing.BuildError` was raised. If this returns - a value, it will be returned by ``url_for``, otherwise the error - will be re-raised. - - Each function in :attr:`url_build_error_handlers` is called with - ``error``, ``endpoint`` and ``values``. If a function returns - ``None`` or raises a ``BuildError``, it is skipped. Otherwise, - its return value is returned by ``url_for``. - - :param error: The active ``BuildError`` being handled. - :param endpoint: The endpoint being built. - :param values: The keyword arguments passed to ``url_for``. - """ - for handler in self.url_build_error_handlers: - try: - rv = handler(error, endpoint, values) - except BuildError as e: - # make error available outside except block - error = e - else: - if rv is not None: - return rv - - # Re-raise if called with an active exception, otherwise raise - # the passed in exception. - if error is sys.exc_info()[1]: - raise - - raise error diff --git a/serverenv/lib/python3.9/site-packages/flask/sansio/blueprints.py b/serverenv/lib/python3.9/site-packages/flask/sansio/blueprints.py deleted file mode 100644 index 4f912cc..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/sansio/blueprints.py +++ /dev/null @@ -1,632 +0,0 @@ -from __future__ import annotations - -import os -import typing as t -from collections import defaultdict -from functools import update_wrapper - -from .. import typing as ft -from .scaffold import _endpoint_from_view_func -from .scaffold import _sentinel -from .scaffold import Scaffold -from .scaffold import setupmethod - -if t.TYPE_CHECKING: # pragma: no cover - from .app import App - -DeferredSetupFunction = t.Callable[["BlueprintSetupState"], None] -T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any]) -T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) -T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) -T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) -T_template_context_processor = t.TypeVar( - "T_template_context_processor", bound=ft.TemplateContextProcessorCallable -) -T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) -T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) -T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) -T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) -T_url_value_preprocessor = t.TypeVar( - "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable -) - - -class BlueprintSetupState: - """Temporary holder object for registering a blueprint with the - application. An instance of this class is created by the - :meth:`~flask.Blueprint.make_setup_state` method and later passed - to all register callback functions. - """ - - def __init__( - self, - blueprint: Blueprint, - app: App, - options: t.Any, - first_registration: bool, - ) -> None: - #: a reference to the current application - self.app = app - - #: a reference to the blueprint that created this setup state. - self.blueprint = blueprint - - #: a dictionary with all options that were passed to the - #: :meth:`~flask.Flask.register_blueprint` method. - self.options = options - - #: as blueprints can be registered multiple times with the - #: application and not everything wants to be registered - #: multiple times on it, this attribute can be used to figure - #: out if the blueprint was registered in the past already. - self.first_registration = first_registration - - subdomain = self.options.get("subdomain") - if subdomain is None: - subdomain = self.blueprint.subdomain - - #: The subdomain that the blueprint should be active for, ``None`` - #: otherwise. - self.subdomain = subdomain - - url_prefix = self.options.get("url_prefix") - if url_prefix is None: - url_prefix = self.blueprint.url_prefix - #: The prefix that should be used for all URLs defined on the - #: blueprint. - self.url_prefix = url_prefix - - self.name = self.options.get("name", blueprint.name) - self.name_prefix = self.options.get("name_prefix", "") - - #: A dictionary with URL defaults that is added to each and every - #: URL that was defined with the blueprint. - self.url_defaults = dict(self.blueprint.url_values_defaults) - self.url_defaults.update(self.options.get("url_defaults", ())) - - def add_url_rule( - self, - rule: str, - endpoint: str | None = None, - view_func: ft.RouteCallable | None = None, - **options: t.Any, - ) -> None: - """A helper method to register a rule (and optionally a view function) - to the application. The endpoint is automatically prefixed with the - blueprint's name. - """ - if self.url_prefix is not None: - if rule: - rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/"))) - else: - rule = self.url_prefix - options.setdefault("subdomain", self.subdomain) - if endpoint is None: - endpoint = _endpoint_from_view_func(view_func) # type: ignore - defaults = self.url_defaults - if "defaults" in options: - defaults = dict(defaults, **options.pop("defaults")) - - self.app.add_url_rule( - rule, - f"{self.name_prefix}.{self.name}.{endpoint}".lstrip("."), - view_func, - defaults=defaults, - **options, - ) - - -class Blueprint(Scaffold): - """Represents a blueprint, a collection of routes and other - app-related functions that can be registered on a real application - later. - - A blueprint is an object that allows defining application functions - without requiring an application object ahead of time. It uses the - same decorators as :class:`~flask.Flask`, but defers the need for an - application by recording them for later registration. - - Decorating a function with a blueprint creates a deferred function - that is called with :class:`~flask.blueprints.BlueprintSetupState` - when the blueprint is registered on an application. - - See :doc:`/blueprints` for more information. - - :param name: The name of the blueprint. Will be prepended to each - endpoint name. - :param import_name: The name of the blueprint package, usually - ``__name__``. This helps locate the ``root_path`` for the - blueprint. - :param static_folder: A folder with static files that should be - served by the blueprint's static route. The path is relative to - the blueprint's root path. Blueprint static files are disabled - by default. - :param static_url_path: The url to serve static files from. - Defaults to ``static_folder``. If the blueprint does not have - a ``url_prefix``, the app's static route will take precedence, - and the blueprint's static files won't be accessible. - :param template_folder: A folder with templates that should be added - to the app's template search path. The path is relative to the - blueprint's root path. Blueprint templates are disabled by - default. Blueprint templates have a lower precedence than those - in the app's templates folder. - :param url_prefix: A path to prepend to all of the blueprint's URLs, - to make them distinct from the rest of the app's routes. - :param subdomain: A subdomain that blueprint routes will match on by - default. - :param url_defaults: A dict of default values that blueprint routes - will receive by default. - :param root_path: By default, the blueprint will automatically set - this based on ``import_name``. In certain situations this - automatic detection can fail, so the path can be specified - manually instead. - - .. versionchanged:: 1.1.0 - Blueprints have a ``cli`` group to register nested CLI commands. - The ``cli_group`` parameter controls the name of the group under - the ``flask`` command. - - .. versionadded:: 0.7 - """ - - _got_registered_once = False - - def __init__( - self, - name: str, - import_name: str, - static_folder: str | os.PathLike[str] | None = None, - static_url_path: str | None = None, - template_folder: str | os.PathLike[str] | None = None, - url_prefix: str | None = None, - subdomain: str | None = None, - url_defaults: dict[str, t.Any] | None = None, - root_path: str | None = None, - cli_group: str | None = _sentinel, # type: ignore[assignment] - ): - super().__init__( - import_name=import_name, - static_folder=static_folder, - static_url_path=static_url_path, - template_folder=template_folder, - root_path=root_path, - ) - - if not name: - raise ValueError("'name' may not be empty.") - - if "." in name: - raise ValueError("'name' may not contain a dot '.' character.") - - self.name = name - self.url_prefix = url_prefix - self.subdomain = subdomain - self.deferred_functions: list[DeferredSetupFunction] = [] - - if url_defaults is None: - url_defaults = {} - - self.url_values_defaults = url_defaults - self.cli_group = cli_group - self._blueprints: list[tuple[Blueprint, dict[str, t.Any]]] = [] - - def _check_setup_finished(self, f_name: str) -> None: - if self._got_registered_once: - raise AssertionError( - f"The setup method '{f_name}' can no longer be called on the blueprint" - f" '{self.name}'. It has already been registered at least once, any" - " changes will not be applied consistently.\n" - "Make sure all imports, decorators, functions, etc. needed to set up" - " the blueprint are done before registering it." - ) - - @setupmethod - def record(self, func: DeferredSetupFunction) -> None: - """Registers a function that is called when the blueprint is - registered on the application. This function is called with the - state as argument as returned by the :meth:`make_setup_state` - method. - """ - self.deferred_functions.append(func) - - @setupmethod - def record_once(self, func: DeferredSetupFunction) -> None: - """Works like :meth:`record` but wraps the function in another - function that will ensure the function is only called once. If the - blueprint is registered a second time on the application, the - function passed is not called. - """ - - def wrapper(state: BlueprintSetupState) -> None: - if state.first_registration: - func(state) - - self.record(update_wrapper(wrapper, func)) - - def make_setup_state( - self, app: App, options: dict[str, t.Any], first_registration: bool = False - ) -> BlueprintSetupState: - """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` - object that is later passed to the register callback functions. - Subclasses can override this to return a subclass of the setup state. - """ - return BlueprintSetupState(self, app, options, first_registration) - - @setupmethod - def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: - """Register a :class:`~flask.Blueprint` on this blueprint. Keyword - arguments passed to this method will override the defaults set - on the blueprint. - - .. versionchanged:: 2.0.1 - The ``name`` option can be used to change the (pre-dotted) - name the blueprint is registered with. This allows the same - blueprint to be registered multiple times with unique names - for ``url_for``. - - .. versionadded:: 2.0 - """ - if blueprint is self: - raise ValueError("Cannot register a blueprint on itself") - self._blueprints.append((blueprint, options)) - - def register(self, app: App, options: dict[str, t.Any]) -> None: - """Called by :meth:`Flask.register_blueprint` to register all - views and callbacks registered on the blueprint with the - application. Creates a :class:`.BlueprintSetupState` and calls - each :meth:`record` callback with it. - - :param app: The application this blueprint is being registered - with. - :param options: Keyword arguments forwarded from - :meth:`~Flask.register_blueprint`. - - .. versionchanged:: 2.3 - Nested blueprints now correctly apply subdomains. - - .. versionchanged:: 2.1 - Registering the same blueprint with the same name multiple - times is an error. - - .. versionchanged:: 2.0.1 - Nested blueprints are registered with their dotted name. - This allows different blueprints with the same name to be - nested at different locations. - - .. versionchanged:: 2.0.1 - The ``name`` option can be used to change the (pre-dotted) - name the blueprint is registered with. This allows the same - blueprint to be registered multiple times with unique names - for ``url_for``. - """ - name_prefix = options.get("name_prefix", "") - self_name = options.get("name", self.name) - name = f"{name_prefix}.{self_name}".lstrip(".") - - if name in app.blueprints: - bp_desc = "this" if app.blueprints[name] is self else "a different" - existing_at = f" '{name}'" if self_name != name else "" - - raise ValueError( - f"The name '{self_name}' is already registered for" - f" {bp_desc} blueprint{existing_at}. Use 'name=' to" - f" provide a unique name." - ) - - first_bp_registration = not any(bp is self for bp in app.blueprints.values()) - first_name_registration = name not in app.blueprints - - app.blueprints[name] = self - self._got_registered_once = True - state = self.make_setup_state(app, options, first_bp_registration) - - if self.has_static_folder: - state.add_url_rule( - f"{self.static_url_path}/", - view_func=self.send_static_file, # type: ignore[attr-defined] - endpoint="static", - ) - - # Merge blueprint data into parent. - if first_bp_registration or first_name_registration: - self._merge_blueprint_funcs(app, name) - - for deferred in self.deferred_functions: - deferred(state) - - cli_resolved_group = options.get("cli_group", self.cli_group) - - if self.cli.commands: - if cli_resolved_group is None: - app.cli.commands.update(self.cli.commands) - elif cli_resolved_group is _sentinel: - self.cli.name = name - app.cli.add_command(self.cli) - else: - self.cli.name = cli_resolved_group - app.cli.add_command(self.cli) - - for blueprint, bp_options in self._blueprints: - bp_options = bp_options.copy() - bp_url_prefix = bp_options.get("url_prefix") - bp_subdomain = bp_options.get("subdomain") - - if bp_subdomain is None: - bp_subdomain = blueprint.subdomain - - if state.subdomain is not None and bp_subdomain is not None: - bp_options["subdomain"] = bp_subdomain + "." + state.subdomain - elif bp_subdomain is not None: - bp_options["subdomain"] = bp_subdomain - elif state.subdomain is not None: - bp_options["subdomain"] = state.subdomain - - if bp_url_prefix is None: - bp_url_prefix = blueprint.url_prefix - - if state.url_prefix is not None and bp_url_prefix is not None: - bp_options["url_prefix"] = ( - state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") - ) - elif bp_url_prefix is not None: - bp_options["url_prefix"] = bp_url_prefix - elif state.url_prefix is not None: - bp_options["url_prefix"] = state.url_prefix - - bp_options["name_prefix"] = name - blueprint.register(app, bp_options) - - def _merge_blueprint_funcs(self, app: App, name: str) -> None: - def extend( - bp_dict: dict[ft.AppOrBlueprintKey, list[t.Any]], - parent_dict: dict[ft.AppOrBlueprintKey, list[t.Any]], - ) -> None: - for key, values in bp_dict.items(): - key = name if key is None else f"{name}.{key}" - parent_dict[key].extend(values) - - for key, value in self.error_handler_spec.items(): - key = name if key is None else f"{name}.{key}" - value = defaultdict( - dict, - { - code: {exc_class: func for exc_class, func in code_values.items()} - for code, code_values in value.items() - }, - ) - app.error_handler_spec[key] = value - - for endpoint, func in self.view_functions.items(): - app.view_functions[endpoint] = func - - extend(self.before_request_funcs, app.before_request_funcs) - extend(self.after_request_funcs, app.after_request_funcs) - extend( - self.teardown_request_funcs, - app.teardown_request_funcs, - ) - extend(self.url_default_functions, app.url_default_functions) - extend(self.url_value_preprocessors, app.url_value_preprocessors) - extend(self.template_context_processors, app.template_context_processors) - - @setupmethod - def add_url_rule( - self, - rule: str, - endpoint: str | None = None, - view_func: ft.RouteCallable | None = None, - provide_automatic_options: bool | None = None, - **options: t.Any, - ) -> None: - """Register a URL rule with the blueprint. See :meth:`.Flask.add_url_rule` for - full documentation. - - The URL rule is prefixed with the blueprint's URL prefix. The endpoint name, - used with :func:`url_for`, is prefixed with the blueprint's name. - """ - if endpoint and "." in endpoint: - raise ValueError("'endpoint' may not contain a dot '.' character.") - - if view_func and hasattr(view_func, "__name__") and "." in view_func.__name__: - raise ValueError("'view_func' name may not contain a dot '.' character.") - - self.record( - lambda s: s.add_url_rule( - rule, - endpoint, - view_func, - provide_automatic_options=provide_automatic_options, - **options, - ) - ) - - @setupmethod - def app_template_filter( - self, name: str | None = None - ) -> t.Callable[[T_template_filter], T_template_filter]: - """Register a template filter, available in any template rendered by the - application. Equivalent to :meth:`.Flask.template_filter`. - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - - def decorator(f: T_template_filter) -> T_template_filter: - self.add_app_template_filter(f, name=name) - return f - - return decorator - - @setupmethod - def add_app_template_filter( - self, f: ft.TemplateFilterCallable, name: str | None = None - ) -> None: - """Register a template filter, available in any template rendered by the - application. Works like the :meth:`app_template_filter` decorator. Equivalent to - :meth:`.Flask.add_template_filter`. - - :param name: the optional name of the filter, otherwise the - function name will be used. - """ - - def register_template(state: BlueprintSetupState) -> None: - state.app.jinja_env.filters[name or f.__name__] = f - - self.record_once(register_template) - - @setupmethod - def app_template_test( - self, name: str | None = None - ) -> t.Callable[[T_template_test], T_template_test]: - """Register a template test, available in any template rendered by the - application. Equivalent to :meth:`.Flask.template_test`. - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - - def decorator(f: T_template_test) -> T_template_test: - self.add_app_template_test(f, name=name) - return f - - return decorator - - @setupmethod - def add_app_template_test( - self, f: ft.TemplateTestCallable, name: str | None = None - ) -> None: - """Register a template test, available in any template rendered by the - application. Works like the :meth:`app_template_test` decorator. Equivalent to - :meth:`.Flask.add_template_test`. - - .. versionadded:: 0.10 - - :param name: the optional name of the test, otherwise the - function name will be used. - """ - - def register_template(state: BlueprintSetupState) -> None: - state.app.jinja_env.tests[name or f.__name__] = f - - self.record_once(register_template) - - @setupmethod - def app_template_global( - self, name: str | None = None - ) -> t.Callable[[T_template_global], T_template_global]: - """Register a template global, available in any template rendered by the - application. Equivalent to :meth:`.Flask.template_global`. - - .. versionadded:: 0.10 - - :param name: the optional name of the global, otherwise the - function name will be used. - """ - - def decorator(f: T_template_global) -> T_template_global: - self.add_app_template_global(f, name=name) - return f - - return decorator - - @setupmethod - def add_app_template_global( - self, f: ft.TemplateGlobalCallable, name: str | None = None - ) -> None: - """Register a template global, available in any template rendered by the - application. Works like the :meth:`app_template_global` decorator. Equivalent to - :meth:`.Flask.add_template_global`. - - .. versionadded:: 0.10 - - :param name: the optional name of the global, otherwise the - function name will be used. - """ - - def register_template(state: BlueprintSetupState) -> None: - state.app.jinja_env.globals[name or f.__name__] = f - - self.record_once(register_template) - - @setupmethod - def before_app_request(self, f: T_before_request) -> T_before_request: - """Like :meth:`before_request`, but before every request, not only those handled - by the blueprint. Equivalent to :meth:`.Flask.before_request`. - """ - self.record_once( - lambda s: s.app.before_request_funcs.setdefault(None, []).append(f) - ) - return f - - @setupmethod - def after_app_request(self, f: T_after_request) -> T_after_request: - """Like :meth:`after_request`, but after every request, not only those handled - by the blueprint. Equivalent to :meth:`.Flask.after_request`. - """ - self.record_once( - lambda s: s.app.after_request_funcs.setdefault(None, []).append(f) - ) - return f - - @setupmethod - def teardown_app_request(self, f: T_teardown) -> T_teardown: - """Like :meth:`teardown_request`, but after every request, not only those - handled by the blueprint. Equivalent to :meth:`.Flask.teardown_request`. - """ - self.record_once( - lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f) - ) - return f - - @setupmethod - def app_context_processor( - self, f: T_template_context_processor - ) -> T_template_context_processor: - """Like :meth:`context_processor`, but for templates rendered by every view, not - only by the blueprint. Equivalent to :meth:`.Flask.context_processor`. - """ - self.record_once( - lambda s: s.app.template_context_processors.setdefault(None, []).append(f) - ) - return f - - @setupmethod - def app_errorhandler( - self, code: type[Exception] | int - ) -> t.Callable[[T_error_handler], T_error_handler]: - """Like :meth:`errorhandler`, but for every request, not only those handled by - the blueprint. Equivalent to :meth:`.Flask.errorhandler`. - """ - - def decorator(f: T_error_handler) -> T_error_handler: - def from_blueprint(state: BlueprintSetupState) -> None: - state.app.errorhandler(code)(f) - - self.record_once(from_blueprint) - return f - - return decorator - - @setupmethod - def app_url_value_preprocessor( - self, f: T_url_value_preprocessor - ) -> T_url_value_preprocessor: - """Like :meth:`url_value_preprocessor`, but for every request, not only those - handled by the blueprint. Equivalent to :meth:`.Flask.url_value_preprocessor`. - """ - self.record_once( - lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f) - ) - return f - - @setupmethod - def app_url_defaults(self, f: T_url_defaults) -> T_url_defaults: - """Like :meth:`url_defaults`, but for every request, not only those handled by - the blueprint. Equivalent to :meth:`.Flask.url_defaults`. - """ - self.record_once( - lambda s: s.app.url_default_functions.setdefault(None, []).append(f) - ) - return f diff --git a/serverenv/lib/python3.9/site-packages/flask/sansio/scaffold.py b/serverenv/lib/python3.9/site-packages/flask/sansio/scaffold.py deleted file mode 100644 index 3a839f5..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/sansio/scaffold.py +++ /dev/null @@ -1,792 +0,0 @@ -from __future__ import annotations - -import importlib.util -import os -import pathlib -import sys -import typing as t -from collections import defaultdict -from functools import update_wrapper - -from jinja2 import BaseLoader -from jinja2 import FileSystemLoader -from werkzeug.exceptions import default_exceptions -from werkzeug.exceptions import HTTPException -from werkzeug.utils import cached_property - -from .. import typing as ft -from ..helpers import get_root_path -from ..templating import _default_template_ctx_processor - -if t.TYPE_CHECKING: # pragma: no cover - from click import Group - -# a singleton sentinel value for parameter defaults -_sentinel = object() - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) -T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable[t.Any]) -T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) -T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) -T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) -T_template_context_processor = t.TypeVar( - "T_template_context_processor", bound=ft.TemplateContextProcessorCallable -) -T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) -T_url_value_preprocessor = t.TypeVar( - "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable -) -T_route = t.TypeVar("T_route", bound=ft.RouteCallable) - - -def setupmethod(f: F) -> F: - f_name = f.__name__ - - def wrapper_func(self: Scaffold, *args: t.Any, **kwargs: t.Any) -> t.Any: - self._check_setup_finished(f_name) - return f(self, *args, **kwargs) - - return t.cast(F, update_wrapper(wrapper_func, f)) - - -class Scaffold: - """Common behavior shared between :class:`~flask.Flask` and - :class:`~flask.blueprints.Blueprint`. - - :param import_name: The import name of the module where this object - is defined. Usually :attr:`__name__` should be used. - :param static_folder: Path to a folder of static files to serve. - If this is set, a static route will be added. - :param static_url_path: URL prefix for the static route. - :param template_folder: Path to a folder containing template files. - for rendering. If this is set, a Jinja loader will be added. - :param root_path: The path that static, template, and resource files - are relative to. Typically not set, it is discovered based on - the ``import_name``. - - .. versionadded:: 2.0 - """ - - cli: Group - name: str - _static_folder: str | None = None - _static_url_path: str | None = None - - def __init__( - self, - import_name: str, - static_folder: str | os.PathLike[str] | None = None, - static_url_path: str | None = None, - template_folder: str | os.PathLike[str] | None = None, - root_path: str | None = None, - ): - #: The name of the package or module that this object belongs - #: to. Do not change this once it is set by the constructor. - self.import_name = import_name - - self.static_folder = static_folder # type: ignore - self.static_url_path = static_url_path - - #: The path to the templates folder, relative to - #: :attr:`root_path`, to add to the template loader. ``None`` if - #: templates should not be added. - self.template_folder = template_folder - - if root_path is None: - root_path = get_root_path(self.import_name) - - #: Absolute path to the package on the filesystem. Used to look - #: up resources contained in the package. - self.root_path = root_path - - #: A dictionary mapping endpoint names to view functions. - #: - #: To register a view function, use the :meth:`route` decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.view_functions: dict[str, ft.RouteCallable] = {} - - #: A data structure of registered error handlers, in the format - #: ``{scope: {code: {class: handler}}}``. The ``scope`` key is - #: the name of a blueprint the handlers are active for, or - #: ``None`` for all requests. The ``code`` key is the HTTP - #: status code for ``HTTPException``, or ``None`` for - #: other exceptions. The innermost dictionary maps exception - #: classes to handler functions. - #: - #: To register an error handler, use the :meth:`errorhandler` - #: decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.error_handler_spec: dict[ - ft.AppOrBlueprintKey, - dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]], - ] = defaultdict(lambda: defaultdict(dict)) - - #: A data structure of functions to call at the beginning of - #: each request, in the format ``{scope: [functions]}``. The - #: ``scope`` key is the name of a blueprint the functions are - #: active for, or ``None`` for all requests. - #: - #: To register a function, use the :meth:`before_request` - #: decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.before_request_funcs: dict[ - ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable] - ] = defaultdict(list) - - #: A data structure of functions to call at the end of each - #: request, in the format ``{scope: [functions]}``. The - #: ``scope`` key is the name of a blueprint the functions are - #: active for, or ``None`` for all requests. - #: - #: To register a function, use the :meth:`after_request` - #: decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.after_request_funcs: dict[ - ft.AppOrBlueprintKey, list[ft.AfterRequestCallable[t.Any]] - ] = defaultdict(list) - - #: A data structure of functions to call at the end of each - #: request even if an exception is raised, in the format - #: ``{scope: [functions]}``. The ``scope`` key is the name of a - #: blueprint the functions are active for, or ``None`` for all - #: requests. - #: - #: To register a function, use the :meth:`teardown_request` - #: decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.teardown_request_funcs: dict[ - ft.AppOrBlueprintKey, list[ft.TeardownCallable] - ] = defaultdict(list) - - #: A data structure of functions to call to pass extra context - #: values when rendering templates, in the format - #: ``{scope: [functions]}``. The ``scope`` key is the name of a - #: blueprint the functions are active for, or ``None`` for all - #: requests. - #: - #: To register a function, use the :meth:`context_processor` - #: decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.template_context_processors: dict[ - ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable] - ] = defaultdict(list, {None: [_default_template_ctx_processor]}) - - #: A data structure of functions to call to modify the keyword - #: arguments passed to the view function, in the format - #: ``{scope: [functions]}``. The ``scope`` key is the name of a - #: blueprint the functions are active for, or ``None`` for all - #: requests. - #: - #: To register a function, use the - #: :meth:`url_value_preprocessor` decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.url_value_preprocessors: dict[ - ft.AppOrBlueprintKey, - list[ft.URLValuePreprocessorCallable], - ] = defaultdict(list) - - #: A data structure of functions to call to modify the keyword - #: arguments when generating URLs, in the format - #: ``{scope: [functions]}``. The ``scope`` key is the name of a - #: blueprint the functions are active for, or ``None`` for all - #: requests. - #: - #: To register a function, use the :meth:`url_defaults` - #: decorator. - #: - #: This data structure is internal. It should not be modified - #: directly and its format may change at any time. - self.url_default_functions: dict[ - ft.AppOrBlueprintKey, list[ft.URLDefaultCallable] - ] = defaultdict(list) - - def __repr__(self) -> str: - return f"<{type(self).__name__} {self.name!r}>" - - def _check_setup_finished(self, f_name: str) -> None: - raise NotImplementedError - - @property - def static_folder(self) -> str | None: - """The absolute path to the configured static folder. ``None`` - if no static folder is set. - """ - if self._static_folder is not None: - return os.path.join(self.root_path, self._static_folder) - else: - return None - - @static_folder.setter - def static_folder(self, value: str | os.PathLike[str] | None) -> None: - if value is not None: - value = os.fspath(value).rstrip(r"\/") - - self._static_folder = value - - @property - def has_static_folder(self) -> bool: - """``True`` if :attr:`static_folder` is set. - - .. versionadded:: 0.5 - """ - return self.static_folder is not None - - @property - def static_url_path(self) -> str | None: - """The URL prefix that the static route will be accessible from. - - If it was not configured during init, it is derived from - :attr:`static_folder`. - """ - if self._static_url_path is not None: - return self._static_url_path - - if self.static_folder is not None: - basename = os.path.basename(self.static_folder) - return f"/{basename}".rstrip("/") - - return None - - @static_url_path.setter - def static_url_path(self, value: str | None) -> None: - if value is not None: - value = value.rstrip("/") - - self._static_url_path = value - - @cached_property - def jinja_loader(self) -> BaseLoader | None: - """The Jinja loader for this object's templates. By default this - is a class :class:`jinja2.loaders.FileSystemLoader` to - :attr:`template_folder` if it is set. - - .. versionadded:: 0.5 - """ - if self.template_folder is not None: - return FileSystemLoader(os.path.join(self.root_path, self.template_folder)) - else: - return None - - def _method_route( - self, - method: str, - rule: str, - options: dict[str, t.Any], - ) -> t.Callable[[T_route], T_route]: - if "methods" in options: - raise TypeError("Use the 'route' decorator to use the 'methods' argument.") - - return self.route(rule, methods=[method], **options) - - @setupmethod - def get(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: - """Shortcut for :meth:`route` with ``methods=["GET"]``. - - .. versionadded:: 2.0 - """ - return self._method_route("GET", rule, options) - - @setupmethod - def post(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: - """Shortcut for :meth:`route` with ``methods=["POST"]``. - - .. versionadded:: 2.0 - """ - return self._method_route("POST", rule, options) - - @setupmethod - def put(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: - """Shortcut for :meth:`route` with ``methods=["PUT"]``. - - .. versionadded:: 2.0 - """ - return self._method_route("PUT", rule, options) - - @setupmethod - def delete(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: - """Shortcut for :meth:`route` with ``methods=["DELETE"]``. - - .. versionadded:: 2.0 - """ - return self._method_route("DELETE", rule, options) - - @setupmethod - def patch(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: - """Shortcut for :meth:`route` with ``methods=["PATCH"]``. - - .. versionadded:: 2.0 - """ - return self._method_route("PATCH", rule, options) - - @setupmethod - def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: - """Decorate a view function to register it with the given URL - rule and options. Calls :meth:`add_url_rule`, which has more - details about the implementation. - - .. code-block:: python - - @app.route("/") - def index(): - return "Hello, World!" - - See :ref:`url-route-registrations`. - - The endpoint name for the route defaults to the name of the view - function if the ``endpoint`` parameter isn't passed. - - The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` and - ``OPTIONS`` are added automatically. - - :param rule: The URL rule string. - :param options: Extra options passed to the - :class:`~werkzeug.routing.Rule` object. - """ - - def decorator(f: T_route) -> T_route: - endpoint = options.pop("endpoint", None) - self.add_url_rule(rule, endpoint, f, **options) - return f - - return decorator - - @setupmethod - def add_url_rule( - self, - rule: str, - endpoint: str | None = None, - view_func: ft.RouteCallable | None = None, - provide_automatic_options: bool | None = None, - **options: t.Any, - ) -> None: - """Register a rule for routing incoming requests and building - URLs. The :meth:`route` decorator is a shortcut to call this - with the ``view_func`` argument. These are equivalent: - - .. code-block:: python - - @app.route("/") - def index(): - ... - - .. code-block:: python - - def index(): - ... - - app.add_url_rule("/", view_func=index) - - See :ref:`url-route-registrations`. - - The endpoint name for the route defaults to the name of the view - function if the ``endpoint`` parameter isn't passed. An error - will be raised if a function has already been registered for the - endpoint. - - The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` is - always added automatically, and ``OPTIONS`` is added - automatically by default. - - ``view_func`` does not necessarily need to be passed, but if the - rule should participate in routing an endpoint name must be - associated with a view function at some point with the - :meth:`endpoint` decorator. - - .. code-block:: python - - app.add_url_rule("/", endpoint="index") - - @app.endpoint("index") - def index(): - ... - - If ``view_func`` has a ``required_methods`` attribute, those - methods are added to the passed and automatic methods. If it - has a ``provide_automatic_methods`` attribute, it is used as the - default if the parameter is not passed. - - :param rule: The URL rule string. - :param endpoint: The endpoint name to associate with the rule - and view function. Used when routing and building URLs. - Defaults to ``view_func.__name__``. - :param view_func: The view function to associate with the - endpoint name. - :param provide_automatic_options: Add the ``OPTIONS`` method and - respond to ``OPTIONS`` requests automatically. - :param options: Extra options passed to the - :class:`~werkzeug.routing.Rule` object. - """ - raise NotImplementedError - - @setupmethod - def endpoint(self, endpoint: str) -> t.Callable[[F], F]: - """Decorate a view function to register it for the given - endpoint. Used if a rule is added without a ``view_func`` with - :meth:`add_url_rule`. - - .. code-block:: python - - app.add_url_rule("/ex", endpoint="example") - - @app.endpoint("example") - def example(): - ... - - :param endpoint: The endpoint name to associate with the view - function. - """ - - def decorator(f: F) -> F: - self.view_functions[endpoint] = f - return f - - return decorator - - @setupmethod - def before_request(self, f: T_before_request) -> T_before_request: - """Register a function to run before each request. - - For example, this can be used to open a database connection, or - to load the logged in user from the session. - - .. code-block:: python - - @app.before_request - def load_user(): - if "user_id" in session: - g.user = db.session.get(session["user_id"]) - - The function will be called without any arguments. If it returns - a non-``None`` value, the value is handled as if it was the - return value from the view, and further request handling is - stopped. - - This is available on both app and blueprint objects. When used on an app, this - executes before every request. When used on a blueprint, this executes before - every request that the blueprint handles. To register with a blueprint and - execute before every request, use :meth:`.Blueprint.before_app_request`. - """ - self.before_request_funcs.setdefault(None, []).append(f) - return f - - @setupmethod - def after_request(self, f: T_after_request) -> T_after_request: - """Register a function to run after each request to this object. - - The function is called with the response object, and must return - a response object. This allows the functions to modify or - replace the response before it is sent. - - If a function raises an exception, any remaining - ``after_request`` functions will not be called. Therefore, this - should not be used for actions that must execute, such as to - close resources. Use :meth:`teardown_request` for that. - - This is available on both app and blueprint objects. When used on an app, this - executes after every request. When used on a blueprint, this executes after - every request that the blueprint handles. To register with a blueprint and - execute after every request, use :meth:`.Blueprint.after_app_request`. - """ - self.after_request_funcs.setdefault(None, []).append(f) - return f - - @setupmethod - def teardown_request(self, f: T_teardown) -> T_teardown: - """Register a function to be called when the request context is - popped. Typically this happens at the end of each request, but - contexts may be pushed manually as well during testing. - - .. code-block:: python - - with app.test_request_context(): - ... - - When the ``with`` block exits (or ``ctx.pop()`` is called), the - teardown functions are called just before the request context is - made inactive. - - When a teardown function was called because of an unhandled - exception it will be passed an error object. If an - :meth:`errorhandler` is registered, it will handle the exception - and the teardown will not receive it. - - Teardown functions must avoid raising exceptions. If they - execute code that might fail they must surround that code with a - ``try``/``except`` block and log any errors. - - The return values of teardown functions are ignored. - - This is available on both app and blueprint objects. When used on an app, this - executes after every request. When used on a blueprint, this executes after - every request that the blueprint handles. To register with a blueprint and - execute after every request, use :meth:`.Blueprint.teardown_app_request`. - """ - self.teardown_request_funcs.setdefault(None, []).append(f) - return f - - @setupmethod - def context_processor( - self, - f: T_template_context_processor, - ) -> T_template_context_processor: - """Registers a template context processor function. These functions run before - rendering a template. The keys of the returned dict are added as variables - available in the template. - - This is available on both app and blueprint objects. When used on an app, this - is called for every rendered template. When used on a blueprint, this is called - for templates rendered from the blueprint's views. To register with a blueprint - and affect every template, use :meth:`.Blueprint.app_context_processor`. - """ - self.template_context_processors[None].append(f) - return f - - @setupmethod - def url_value_preprocessor( - self, - f: T_url_value_preprocessor, - ) -> T_url_value_preprocessor: - """Register a URL value preprocessor function for all view - functions in the application. These functions will be called before the - :meth:`before_request` functions. - - The function can modify the values captured from the matched url before - they are passed to the view. For example, this can be used to pop a - common language code value and place it in ``g`` rather than pass it to - every view. - - The function is passed the endpoint name and values dict. The return - value is ignored. - - This is available on both app and blueprint objects. When used on an app, this - is called for every request. When used on a blueprint, this is called for - requests that the blueprint handles. To register with a blueprint and affect - every request, use :meth:`.Blueprint.app_url_value_preprocessor`. - """ - self.url_value_preprocessors[None].append(f) - return f - - @setupmethod - def url_defaults(self, f: T_url_defaults) -> T_url_defaults: - """Callback function for URL defaults for all view functions of the - application. It's called with the endpoint and values and should - update the values passed in place. - - This is available on both app and blueprint objects. When used on an app, this - is called for every request. When used on a blueprint, this is called for - requests that the blueprint handles. To register with a blueprint and affect - every request, use :meth:`.Blueprint.app_url_defaults`. - """ - self.url_default_functions[None].append(f) - return f - - @setupmethod - def errorhandler( - self, code_or_exception: type[Exception] | int - ) -> t.Callable[[T_error_handler], T_error_handler]: - """Register a function to handle errors by code or exception class. - - A decorator that is used to register a function given an - error code. Example:: - - @app.errorhandler(404) - def page_not_found(error): - return 'This page does not exist', 404 - - You can also register handlers for arbitrary exceptions:: - - @app.errorhandler(DatabaseError) - def special_exception_handler(error): - return 'Database connection failed', 500 - - This is available on both app and blueprint objects. When used on an app, this - can handle errors from every request. When used on a blueprint, this can handle - errors from requests that the blueprint handles. To register with a blueprint - and affect every request, use :meth:`.Blueprint.app_errorhandler`. - - .. versionadded:: 0.7 - Use :meth:`register_error_handler` instead of modifying - :attr:`error_handler_spec` directly, for application wide error - handlers. - - .. versionadded:: 0.7 - One can now additionally also register custom exception types - that do not necessarily have to be a subclass of the - :class:`~werkzeug.exceptions.HTTPException` class. - - :param code_or_exception: the code as integer for the handler, or - an arbitrary exception - """ - - def decorator(f: T_error_handler) -> T_error_handler: - self.register_error_handler(code_or_exception, f) - return f - - return decorator - - @setupmethod - def register_error_handler( - self, - code_or_exception: type[Exception] | int, - f: ft.ErrorHandlerCallable, - ) -> None: - """Alternative error attach function to the :meth:`errorhandler` - decorator that is more straightforward to use for non decorator - usage. - - .. versionadded:: 0.7 - """ - exc_class, code = self._get_exc_class_and_code(code_or_exception) - self.error_handler_spec[None][code][exc_class] = f - - @staticmethod - def _get_exc_class_and_code( - exc_class_or_code: type[Exception] | int, - ) -> tuple[type[Exception], int | None]: - """Get the exception class being handled. For HTTP status codes - or ``HTTPException`` subclasses, return both the exception and - status code. - - :param exc_class_or_code: Any exception class, or an HTTP status - code as an integer. - """ - exc_class: type[Exception] - - if isinstance(exc_class_or_code, int): - try: - exc_class = default_exceptions[exc_class_or_code] - except KeyError: - raise ValueError( - f"'{exc_class_or_code}' is not a recognized HTTP" - " error code. Use a subclass of HTTPException with" - " that code instead." - ) from None - else: - exc_class = exc_class_or_code - - if isinstance(exc_class, Exception): - raise TypeError( - f"{exc_class!r} is an instance, not a class. Handlers" - " can only be registered for Exception classes or HTTP" - " error codes." - ) - - if not issubclass(exc_class, Exception): - raise ValueError( - f"'{exc_class.__name__}' is not a subclass of Exception." - " Handlers can only be registered for Exception classes" - " or HTTP error codes." - ) - - if issubclass(exc_class, HTTPException): - return exc_class, exc_class.code - else: - return exc_class, None - - -def _endpoint_from_view_func(view_func: ft.RouteCallable) -> str: - """Internal helper that returns the default endpoint for a given - function. This always is the function name. - """ - assert view_func is not None, "expected view func if endpoint is not provided." - return view_func.__name__ - - -def _find_package_path(import_name: str) -> str: - """Find the path that contains the package or module.""" - root_mod_name, _, _ = import_name.partition(".") - - try: - root_spec = importlib.util.find_spec(root_mod_name) - - if root_spec is None: - raise ValueError("not found") - except (ImportError, ValueError): - # ImportError: the machinery told us it does not exist - # ValueError: - # - the module name was invalid - # - the module name is __main__ - # - we raised `ValueError` due to `root_spec` being `None` - return os.getcwd() - - if root_spec.submodule_search_locations: - if root_spec.origin is None or root_spec.origin == "namespace": - # namespace package - package_spec = importlib.util.find_spec(import_name) - - if package_spec is not None and package_spec.submodule_search_locations: - # Pick the path in the namespace that contains the submodule. - package_path = pathlib.Path( - os.path.commonpath(package_spec.submodule_search_locations) - ) - search_location = next( - location - for location in root_spec.submodule_search_locations - if package_path.is_relative_to(location) - ) - else: - # Pick the first path. - search_location = root_spec.submodule_search_locations[0] - - return os.path.dirname(search_location) - else: - # package with __init__.py - return os.path.dirname(os.path.dirname(root_spec.origin)) - else: - # module - return os.path.dirname(root_spec.origin) # type: ignore[type-var, return-value] - - -def find_package(import_name: str) -> tuple[str | None, str]: - """Find the prefix that a package is installed under, and the path - that it would be imported from. - - The prefix is the directory containing the standard directory - hierarchy (lib, bin, etc.). If the package is not installed to the - system (:attr:`sys.prefix`) or a virtualenv (``site-packages``), - ``None`` is returned. - - The path is the entry in :attr:`sys.path` that contains the package - for import. If the package is not installed, it's assumed that the - package was imported from the current working directory. - """ - package_path = _find_package_path(import_name) - py_prefix = os.path.abspath(sys.prefix) - - # installed to the system - if pathlib.PurePath(package_path).is_relative_to(py_prefix): - return py_prefix, package_path - - site_parent, site_folder = os.path.split(package_path) - - # installed to a virtualenv - if site_folder.lower() == "site-packages": - parent, folder = os.path.split(site_parent) - - # Windows (prefix/lib/site-packages) - if folder.lower() == "lib": - return parent, package_path - - # Unix (prefix/lib/pythonX.Y/site-packages) - if os.path.basename(parent).lower() == "lib": - return os.path.dirname(parent), package_path - - # something else (prefix/site-packages) - return site_parent, package_path - - # not installed - return None, package_path diff --git a/serverenv/lib/python3.9/site-packages/flask/sessions.py b/serverenv/lib/python3.9/site-packages/flask/sessions.py deleted file mode 100644 index 4ffde71..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/sessions.py +++ /dev/null @@ -1,399 +0,0 @@ -from __future__ import annotations - -import collections.abc as c -import hashlib -import typing as t -from collections.abc import MutableMapping -from datetime import datetime -from datetime import timezone - -from itsdangerous import BadSignature -from itsdangerous import URLSafeTimedSerializer -from werkzeug.datastructures import CallbackDict - -from .json.tag import TaggedJSONSerializer - -if t.TYPE_CHECKING: # pragma: no cover - import typing_extensions as te - - from .app import Flask - from .wrappers import Request - from .wrappers import Response - - -class SessionMixin(MutableMapping[str, t.Any]): - """Expands a basic dictionary with session attributes.""" - - @property - def permanent(self) -> bool: - """This reflects the ``'_permanent'`` key in the dict.""" - return self.get("_permanent", False) - - @permanent.setter - def permanent(self, value: bool) -> None: - self["_permanent"] = bool(value) - - #: Some implementations can detect whether a session is newly - #: created, but that is not guaranteed. Use with caution. The mixin - # default is hard-coded ``False``. - new = False - - #: Some implementations can detect changes to the session and set - #: this when that happens. The mixin default is hard coded to - #: ``True``. - modified = True - - #: Some implementations can detect when session data is read or - #: written and set this when that happens. The mixin default is hard - #: coded to ``True``. - accessed = True - - -class SecureCookieSession(CallbackDict[str, t.Any], SessionMixin): - """Base class for sessions based on signed cookies. - - This session backend will set the :attr:`modified` and - :attr:`accessed` attributes. It cannot reliably track whether a - session is new (vs. empty), so :attr:`new` remains hard coded to - ``False``. - """ - - #: When data is changed, this is set to ``True``. Only the session - #: dictionary itself is tracked; if the session contains mutable - #: data (for example a nested dict) then this must be set to - #: ``True`` manually when modifying that data. The session cookie - #: will only be written to the response if this is ``True``. - modified = False - - #: When data is read or written, this is set to ``True``. Used by - # :class:`.SecureCookieSessionInterface` to add a ``Vary: Cookie`` - #: header, which allows caching proxies to cache different pages for - #: different users. - accessed = False - - def __init__( - self, - initial: c.Mapping[str, t.Any] | c.Iterable[tuple[str, t.Any]] | None = None, - ) -> None: - def on_update(self: te.Self) -> None: - self.modified = True - self.accessed = True - - super().__init__(initial, on_update) - - def __getitem__(self, key: str) -> t.Any: - self.accessed = True - return super().__getitem__(key) - - def get(self, key: str, default: t.Any = None) -> t.Any: - self.accessed = True - return super().get(key, default) - - def setdefault(self, key: str, default: t.Any = None) -> t.Any: - self.accessed = True - return super().setdefault(key, default) - - -class NullSession(SecureCookieSession): - """Class used to generate nicer error messages if sessions are not - available. Will still allow read-only access to the empty session - but fail on setting. - """ - - def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: - raise RuntimeError( - "The session is unavailable because no secret " - "key was set. Set the secret_key on the " - "application to something unique and secret." - ) - - __setitem__ = __delitem__ = clear = pop = popitem = update = setdefault = _fail # type: ignore # noqa: B950 - del _fail - - -class SessionInterface: - """The basic interface you have to implement in order to replace the - default session interface which uses werkzeug's securecookie - implementation. The only methods you have to implement are - :meth:`open_session` and :meth:`save_session`, the others have - useful defaults which you don't need to change. - - The session object returned by the :meth:`open_session` method has to - provide a dictionary like interface plus the properties and methods - from the :class:`SessionMixin`. We recommend just subclassing a dict - and adding that mixin:: - - class Session(dict, SessionMixin): - pass - - If :meth:`open_session` returns ``None`` Flask will call into - :meth:`make_null_session` to create a session that acts as replacement - if the session support cannot work because some requirement is not - fulfilled. The default :class:`NullSession` class that is created - will complain that the secret key was not set. - - To replace the session interface on an application all you have to do - is to assign :attr:`flask.Flask.session_interface`:: - - app = Flask(__name__) - app.session_interface = MySessionInterface() - - Multiple requests with the same session may be sent and handled - concurrently. When implementing a new session interface, consider - whether reads or writes to the backing store must be synchronized. - There is no guarantee on the order in which the session for each - request is opened or saved, it will occur in the order that requests - begin and end processing. - - .. versionadded:: 0.8 - """ - - #: :meth:`make_null_session` will look here for the class that should - #: be created when a null session is requested. Likewise the - #: :meth:`is_null_session` method will perform a typecheck against - #: this type. - null_session_class = NullSession - - #: A flag that indicates if the session interface is pickle based. - #: This can be used by Flask extensions to make a decision in regards - #: to how to deal with the session object. - #: - #: .. versionadded:: 0.10 - pickle_based = False - - def make_null_session(self, app: Flask) -> NullSession: - """Creates a null session which acts as a replacement object if the - real session support could not be loaded due to a configuration - error. This mainly aids the user experience because the job of the - null session is to still support lookup without complaining but - modifications are answered with a helpful error message of what - failed. - - This creates an instance of :attr:`null_session_class` by default. - """ - return self.null_session_class() - - def is_null_session(self, obj: object) -> bool: - """Checks if a given object is a null session. Null sessions are - not asked to be saved. - - This checks if the object is an instance of :attr:`null_session_class` - by default. - """ - return isinstance(obj, self.null_session_class) - - def get_cookie_name(self, app: Flask) -> str: - """The name of the session cookie. Uses``app.config["SESSION_COOKIE_NAME"]``.""" - return app.config["SESSION_COOKIE_NAME"] # type: ignore[no-any-return] - - def get_cookie_domain(self, app: Flask) -> str | None: - """The value of the ``Domain`` parameter on the session cookie. If not set, - browsers will only send the cookie to the exact domain it was set from. - Otherwise, they will send it to any subdomain of the given value as well. - - Uses the :data:`SESSION_COOKIE_DOMAIN` config. - - .. versionchanged:: 2.3 - Not set by default, does not fall back to ``SERVER_NAME``. - """ - return app.config["SESSION_COOKIE_DOMAIN"] # type: ignore[no-any-return] - - def get_cookie_path(self, app: Flask) -> str: - """Returns the path for which the cookie should be valid. The - default implementation uses the value from the ``SESSION_COOKIE_PATH`` - config var if it's set, and falls back to ``APPLICATION_ROOT`` or - uses ``/`` if it's ``None``. - """ - return app.config["SESSION_COOKIE_PATH"] or app.config["APPLICATION_ROOT"] # type: ignore[no-any-return] - - def get_cookie_httponly(self, app: Flask) -> bool: - """Returns True if the session cookie should be httponly. This - currently just returns the value of the ``SESSION_COOKIE_HTTPONLY`` - config var. - """ - return app.config["SESSION_COOKIE_HTTPONLY"] # type: ignore[no-any-return] - - def get_cookie_secure(self, app: Flask) -> bool: - """Returns True if the cookie should be secure. This currently - just returns the value of the ``SESSION_COOKIE_SECURE`` setting. - """ - return app.config["SESSION_COOKIE_SECURE"] # type: ignore[no-any-return] - - def get_cookie_samesite(self, app: Flask) -> str | None: - """Return ``'Strict'`` or ``'Lax'`` if the cookie should use the - ``SameSite`` attribute. This currently just returns the value of - the :data:`SESSION_COOKIE_SAMESITE` setting. - """ - return app.config["SESSION_COOKIE_SAMESITE"] # type: ignore[no-any-return] - - def get_cookie_partitioned(self, app: Flask) -> bool: - """Returns True if the cookie should be partitioned. By default, uses - the value of :data:`SESSION_COOKIE_PARTITIONED`. - - .. versionadded:: 3.1 - """ - return app.config["SESSION_COOKIE_PARTITIONED"] # type: ignore[no-any-return] - - def get_expiration_time(self, app: Flask, session: SessionMixin) -> datetime | None: - """A helper method that returns an expiration date for the session - or ``None`` if the session is linked to the browser session. The - default implementation returns now + the permanent session - lifetime configured on the application. - """ - if session.permanent: - return datetime.now(timezone.utc) + app.permanent_session_lifetime - return None - - def should_set_cookie(self, app: Flask, session: SessionMixin) -> bool: - """Used by session backends to determine if a ``Set-Cookie`` header - should be set for this session cookie for this response. If the session - has been modified, the cookie is set. If the session is permanent and - the ``SESSION_REFRESH_EACH_REQUEST`` config is true, the cookie is - always set. - - This check is usually skipped if the session was deleted. - - .. versionadded:: 0.11 - """ - - return session.modified or ( - session.permanent and app.config["SESSION_REFRESH_EACH_REQUEST"] - ) - - def open_session(self, app: Flask, request: Request) -> SessionMixin | None: - """This is called at the beginning of each request, after - pushing the request context, before matching the URL. - - This must return an object which implements a dictionary-like - interface as well as the :class:`SessionMixin` interface. - - This will return ``None`` to indicate that loading failed in - some way that is not immediately an error. The request - context will fall back to using :meth:`make_null_session` - in this case. - """ - raise NotImplementedError() - - def save_session( - self, app: Flask, session: SessionMixin, response: Response - ) -> None: - """This is called at the end of each request, after generating - a response, before removing the request context. It is skipped - if :meth:`is_null_session` returns ``True``. - """ - raise NotImplementedError() - - -session_json_serializer = TaggedJSONSerializer() - - -def _lazy_sha1(string: bytes = b"") -> t.Any: - """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include - SHA-1, in which case the import and use as a default would fail before the - developer can configure something else. - """ - return hashlib.sha1(string) - - -class SecureCookieSessionInterface(SessionInterface): - """The default session interface that stores sessions in signed cookies - through the :mod:`itsdangerous` module. - """ - - #: the salt that should be applied on top of the secret key for the - #: signing of cookie based sessions. - salt = "cookie-session" - #: the hash function to use for the signature. The default is sha1 - digest_method = staticmethod(_lazy_sha1) - #: the name of the itsdangerous supported key derivation. The default - #: is hmac. - key_derivation = "hmac" - #: A python serializer for the payload. The default is a compact - #: JSON derived serializer with support for some extra Python types - #: such as datetime objects or tuples. - serializer = session_json_serializer - session_class = SecureCookieSession - - def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer | None: - if not app.secret_key: - return None - - keys: list[str | bytes] = [] - - if fallbacks := app.config["SECRET_KEY_FALLBACKS"]: - keys.extend(fallbacks) - - keys.append(app.secret_key) # itsdangerous expects current key at top - return URLSafeTimedSerializer( - keys, # type: ignore[arg-type] - salt=self.salt, - serializer=self.serializer, - signer_kwargs={ - "key_derivation": self.key_derivation, - "digest_method": self.digest_method, - }, - ) - - def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None: - s = self.get_signing_serializer(app) - if s is None: - return None - val = request.cookies.get(self.get_cookie_name(app)) - if not val: - return self.session_class() - max_age = int(app.permanent_session_lifetime.total_seconds()) - try: - data = s.loads(val, max_age=max_age) - return self.session_class(data) - except BadSignature: - return self.session_class() - - def save_session( - self, app: Flask, session: SessionMixin, response: Response - ) -> None: - name = self.get_cookie_name(app) - domain = self.get_cookie_domain(app) - path = self.get_cookie_path(app) - secure = self.get_cookie_secure(app) - partitioned = self.get_cookie_partitioned(app) - samesite = self.get_cookie_samesite(app) - httponly = self.get_cookie_httponly(app) - - # Add a "Vary: Cookie" header if the session was accessed at all. - if session.accessed: - response.vary.add("Cookie") - - # If the session is modified to be empty, remove the cookie. - # If the session is empty, return without setting the cookie. - if not session: - if session.modified: - response.delete_cookie( - name, - domain=domain, - path=path, - secure=secure, - partitioned=partitioned, - samesite=samesite, - httponly=httponly, - ) - response.vary.add("Cookie") - - return - - if not self.should_set_cookie(app, session): - return - - expires = self.get_expiration_time(app, session) - val = self.get_signing_serializer(app).dumps(dict(session)) # type: ignore[union-attr] - response.set_cookie( - name, - val, - expires=expires, - httponly=httponly, - domain=domain, - path=path, - secure=secure, - partitioned=partitioned, - samesite=samesite, - ) - response.vary.add("Cookie") diff --git a/serverenv/lib/python3.9/site-packages/flask/signals.py b/serverenv/lib/python3.9/site-packages/flask/signals.py deleted file mode 100644 index 444fda9..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/signals.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import annotations - -from blinker import Namespace - -# This namespace is only for signals provided by Flask itself. -_signals = Namespace() - -template_rendered = _signals.signal("template-rendered") -before_render_template = _signals.signal("before-render-template") -request_started = _signals.signal("request-started") -request_finished = _signals.signal("request-finished") -request_tearing_down = _signals.signal("request-tearing-down") -got_request_exception = _signals.signal("got-request-exception") -appcontext_tearing_down = _signals.signal("appcontext-tearing-down") -appcontext_pushed = _signals.signal("appcontext-pushed") -appcontext_popped = _signals.signal("appcontext-popped") -message_flashed = _signals.signal("message-flashed") diff --git a/serverenv/lib/python3.9/site-packages/flask/templating.py b/serverenv/lib/python3.9/site-packages/flask/templating.py deleted file mode 100644 index 618a3b3..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/templating.py +++ /dev/null @@ -1,219 +0,0 @@ -from __future__ import annotations - -import typing as t - -from jinja2 import BaseLoader -from jinja2 import Environment as BaseEnvironment -from jinja2 import Template -from jinja2 import TemplateNotFound - -from .globals import _cv_app -from .globals import _cv_request -from .globals import current_app -from .globals import request -from .helpers import stream_with_context -from .signals import before_render_template -from .signals import template_rendered - -if t.TYPE_CHECKING: # pragma: no cover - from .app import Flask - from .sansio.app import App - from .sansio.scaffold import Scaffold - - -def _default_template_ctx_processor() -> dict[str, t.Any]: - """Default template context processor. Injects `request`, - `session` and `g`. - """ - appctx = _cv_app.get(None) - reqctx = _cv_request.get(None) - rv: dict[str, t.Any] = {} - if appctx is not None: - rv["g"] = appctx.g - if reqctx is not None: - rv["request"] = reqctx.request - rv["session"] = reqctx.session - return rv - - -class Environment(BaseEnvironment): - """Works like a regular Jinja2 environment but has some additional - knowledge of how Flask's blueprint works so that it can prepend the - name of the blueprint to referenced templates if necessary. - """ - - def __init__(self, app: App, **options: t.Any) -> None: - if "loader" not in options: - options["loader"] = app.create_global_jinja_loader() - BaseEnvironment.__init__(self, **options) - self.app = app - - -class DispatchingJinjaLoader(BaseLoader): - """A loader that looks for templates in the application and all - the blueprint folders. - """ - - def __init__(self, app: App) -> None: - self.app = app - - def get_source( - self, environment: BaseEnvironment, template: str - ) -> tuple[str, str | None, t.Callable[[], bool] | None]: - if self.app.config["EXPLAIN_TEMPLATE_LOADING"]: - return self._get_source_explained(environment, template) - return self._get_source_fast(environment, template) - - def _get_source_explained( - self, environment: BaseEnvironment, template: str - ) -> tuple[str, str | None, t.Callable[[], bool] | None]: - attempts = [] - rv: tuple[str, str | None, t.Callable[[], bool] | None] | None - trv: None | (tuple[str, str | None, t.Callable[[], bool] | None]) = None - - for srcobj, loader in self._iter_loaders(template): - try: - rv = loader.get_source(environment, template) - if trv is None: - trv = rv - except TemplateNotFound: - rv = None - attempts.append((loader, srcobj, rv)) - - from .debughelpers import explain_template_loading_attempts - - explain_template_loading_attempts(self.app, template, attempts) - - if trv is not None: - return trv - raise TemplateNotFound(template) - - def _get_source_fast( - self, environment: BaseEnvironment, template: str - ) -> tuple[str, str | None, t.Callable[[], bool] | None]: - for _srcobj, loader in self._iter_loaders(template): - try: - return loader.get_source(environment, template) - except TemplateNotFound: - continue - raise TemplateNotFound(template) - - def _iter_loaders(self, template: str) -> t.Iterator[tuple[Scaffold, BaseLoader]]: - loader = self.app.jinja_loader - if loader is not None: - yield self.app, loader - - for blueprint in self.app.iter_blueprints(): - loader = blueprint.jinja_loader - if loader is not None: - yield blueprint, loader - - def list_templates(self) -> list[str]: - result = set() - loader = self.app.jinja_loader - if loader is not None: - result.update(loader.list_templates()) - - for blueprint in self.app.iter_blueprints(): - loader = blueprint.jinja_loader - if loader is not None: - for template in loader.list_templates(): - result.add(template) - - return list(result) - - -def _render(app: Flask, template: Template, context: dict[str, t.Any]) -> str: - app.update_template_context(context) - before_render_template.send( - app, _async_wrapper=app.ensure_sync, template=template, context=context - ) - rv = template.render(context) - template_rendered.send( - app, _async_wrapper=app.ensure_sync, template=template, context=context - ) - return rv - - -def render_template( - template_name_or_list: str | Template | list[str | Template], - **context: t.Any, -) -> str: - """Render a template by name with the given context. - - :param template_name_or_list: The name of the template to render. If - a list is given, the first name to exist will be rendered. - :param context: The variables to make available in the template. - """ - app = current_app._get_current_object() # type: ignore[attr-defined] - template = app.jinja_env.get_or_select_template(template_name_or_list) - return _render(app, template, context) - - -def render_template_string(source: str, **context: t.Any) -> str: - """Render a template from the given source string with the given - context. - - :param source: The source code of the template to render. - :param context: The variables to make available in the template. - """ - app = current_app._get_current_object() # type: ignore[attr-defined] - template = app.jinja_env.from_string(source) - return _render(app, template, context) - - -def _stream( - app: Flask, template: Template, context: dict[str, t.Any] -) -> t.Iterator[str]: - app.update_template_context(context) - before_render_template.send( - app, _async_wrapper=app.ensure_sync, template=template, context=context - ) - - def generate() -> t.Iterator[str]: - yield from template.generate(context) - template_rendered.send( - app, _async_wrapper=app.ensure_sync, template=template, context=context - ) - - rv = generate() - - # If a request context is active, keep it while generating. - if request: - rv = stream_with_context(rv) - - return rv - - -def stream_template( - template_name_or_list: str | Template | list[str | Template], - **context: t.Any, -) -> t.Iterator[str]: - """Render a template by name with the given context as a stream. - This returns an iterator of strings, which can be used as a - streaming response from a view. - - :param template_name_or_list: The name of the template to render. If - a list is given, the first name to exist will be rendered. - :param context: The variables to make available in the template. - - .. versionadded:: 2.2 - """ - app = current_app._get_current_object() # type: ignore[attr-defined] - template = app.jinja_env.get_or_select_template(template_name_or_list) - return _stream(app, template, context) - - -def stream_template_string(source: str, **context: t.Any) -> t.Iterator[str]: - """Render a template from the given source string with the given - context as a stream. This returns an iterator of strings, which can - be used as a streaming response from a view. - - :param source: The source code of the template to render. - :param context: The variables to make available in the template. - - .. versionadded:: 2.2 - """ - app = current_app._get_current_object() # type: ignore[attr-defined] - template = app.jinja_env.from_string(source) - return _stream(app, template, context) diff --git a/serverenv/lib/python3.9/site-packages/flask/testing.py b/serverenv/lib/python3.9/site-packages/flask/testing.py deleted file mode 100644 index da156cc..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/testing.py +++ /dev/null @@ -1,298 +0,0 @@ -from __future__ import annotations - -import importlib.metadata -import typing as t -from contextlib import contextmanager -from contextlib import ExitStack -from copy import copy -from types import TracebackType -from urllib.parse import urlsplit - -import werkzeug.test -from click.testing import CliRunner -from click.testing import Result -from werkzeug.test import Client -from werkzeug.wrappers import Request as BaseRequest - -from .cli import ScriptInfo -from .sessions import SessionMixin - -if t.TYPE_CHECKING: # pragma: no cover - from _typeshed.wsgi import WSGIEnvironment - from werkzeug.test import TestResponse - - from .app import Flask - - -class EnvironBuilder(werkzeug.test.EnvironBuilder): - """An :class:`~werkzeug.test.EnvironBuilder`, that takes defaults from the - application. - - :param app: The Flask application to configure the environment from. - :param path: URL path being requested. - :param base_url: Base URL where the app is being served, which - ``path`` is relative to. If not given, built from - :data:`PREFERRED_URL_SCHEME`, ``subdomain``, - :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. - :param subdomain: Subdomain name to append to :data:`SERVER_NAME`. - :param url_scheme: Scheme to use instead of - :data:`PREFERRED_URL_SCHEME`. - :param json: If given, this is serialized as JSON and passed as - ``data``. Also defaults ``content_type`` to - ``application/json``. - :param args: other positional arguments passed to - :class:`~werkzeug.test.EnvironBuilder`. - :param kwargs: other keyword arguments passed to - :class:`~werkzeug.test.EnvironBuilder`. - """ - - def __init__( - self, - app: Flask, - path: str = "/", - base_url: str | None = None, - subdomain: str | None = None, - url_scheme: str | None = None, - *args: t.Any, - **kwargs: t.Any, - ) -> None: - assert not (base_url or subdomain or url_scheme) or ( - base_url is not None - ) != bool(subdomain or url_scheme), ( - 'Cannot pass "subdomain" or "url_scheme" with "base_url".' - ) - - if base_url is None: - http_host = app.config.get("SERVER_NAME") or "localhost" - app_root = app.config["APPLICATION_ROOT"] - - if subdomain: - http_host = f"{subdomain}.{http_host}" - - if url_scheme is None: - url_scheme = app.config["PREFERRED_URL_SCHEME"] - - url = urlsplit(path) - base_url = ( - f"{url.scheme or url_scheme}://{url.netloc or http_host}" - f"/{app_root.lstrip('/')}" - ) - path = url.path - - if url.query: - path = f"{path}?{url.query}" - - self.app = app - super().__init__(path, base_url, *args, **kwargs) - - def json_dumps(self, obj: t.Any, **kwargs: t.Any) -> str: # type: ignore - """Serialize ``obj`` to a JSON-formatted string. - - The serialization will be configured according to the config associated - with this EnvironBuilder's ``app``. - """ - return self.app.json.dumps(obj, **kwargs) - - -_werkzeug_version = "" - - -def _get_werkzeug_version() -> str: - global _werkzeug_version - - if not _werkzeug_version: - _werkzeug_version = importlib.metadata.version("werkzeug") - - return _werkzeug_version - - -class FlaskClient(Client): - """Works like a regular Werkzeug test client but has knowledge about - Flask's contexts to defer the cleanup of the request context until - the end of a ``with`` block. For general information about how to - use this class refer to :class:`werkzeug.test.Client`. - - .. versionchanged:: 0.12 - `app.test_client()` includes preset default environment, which can be - set after instantiation of the `app.test_client()` object in - `client.environ_base`. - - Basic usage is outlined in the :doc:`/testing` chapter. - """ - - application: Flask - - def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: - super().__init__(*args, **kwargs) - self.preserve_context = False - self._new_contexts: list[t.ContextManager[t.Any]] = [] - self._context_stack = ExitStack() - self.environ_base = { - "REMOTE_ADDR": "127.0.0.1", - "HTTP_USER_AGENT": f"Werkzeug/{_get_werkzeug_version()}", - } - - @contextmanager - def session_transaction( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Iterator[SessionMixin]: - """When used in combination with a ``with`` statement this opens a - session transaction. This can be used to modify the session that - the test client uses. Once the ``with`` block is left the session is - stored back. - - :: - - with client.session_transaction() as session: - session['value'] = 42 - - Internally this is implemented by going through a temporary test - request context and since session handling could depend on - request variables this function accepts the same arguments as - :meth:`~flask.Flask.test_request_context` which are directly - passed through. - """ - if self._cookies is None: - raise TypeError( - "Cookies are disabled. Create a client with 'use_cookies=True'." - ) - - app = self.application - ctx = app.test_request_context(*args, **kwargs) - self._add_cookies_to_wsgi(ctx.request.environ) - - with ctx: - sess = app.session_interface.open_session(app, ctx.request) - - if sess is None: - raise RuntimeError("Session backend did not open a session.") - - yield sess - resp = app.response_class() - - if app.session_interface.is_null_session(sess): - return - - with ctx: - app.session_interface.save_session(app, sess, resp) - - self._update_cookies_from_response( - ctx.request.host.partition(":")[0], - ctx.request.path, - resp.headers.getlist("Set-Cookie"), - ) - - def _copy_environ(self, other: WSGIEnvironment) -> WSGIEnvironment: - out = {**self.environ_base, **other} - - if self.preserve_context: - out["werkzeug.debug.preserve_context"] = self._new_contexts.append - - return out - - def _request_from_builder_args( - self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any] - ) -> BaseRequest: - kwargs["environ_base"] = self._copy_environ(kwargs.get("environ_base", {})) - builder = EnvironBuilder(self.application, *args, **kwargs) - - try: - return builder.get_request() - finally: - builder.close() - - def open( - self, - *args: t.Any, - buffered: bool = False, - follow_redirects: bool = False, - **kwargs: t.Any, - ) -> TestResponse: - if args and isinstance( - args[0], (werkzeug.test.EnvironBuilder, dict, BaseRequest) - ): - if isinstance(args[0], werkzeug.test.EnvironBuilder): - builder = copy(args[0]) - builder.environ_base = self._copy_environ(builder.environ_base or {}) # type: ignore[arg-type] - request = builder.get_request() - elif isinstance(args[0], dict): - request = EnvironBuilder.from_environ( - args[0], app=self.application, environ_base=self._copy_environ({}) - ).get_request() - else: - # isinstance(args[0], BaseRequest) - request = copy(args[0]) - request.environ = self._copy_environ(request.environ) - else: - # request is None - request = self._request_from_builder_args(args, kwargs) - - # Pop any previously preserved contexts. This prevents contexts - # from being preserved across redirects or multiple requests - # within a single block. - self._context_stack.close() - - response = super().open( - request, - buffered=buffered, - follow_redirects=follow_redirects, - ) - response.json_module = self.application.json # type: ignore[assignment] - - # Re-push contexts that were preserved during the request. - while self._new_contexts: - cm = self._new_contexts.pop() - self._context_stack.enter_context(cm) - - return response - - def __enter__(self) -> FlaskClient: - if self.preserve_context: - raise RuntimeError("Cannot nest client invocations") - self.preserve_context = True - return self - - def __exit__( - self, - exc_type: type | None, - exc_value: BaseException | None, - tb: TracebackType | None, - ) -> None: - self.preserve_context = False - self._context_stack.close() - - -class FlaskCliRunner(CliRunner): - """A :class:`~click.testing.CliRunner` for testing a Flask app's - CLI commands. Typically created using - :meth:`~flask.Flask.test_cli_runner`. See :ref:`testing-cli`. - """ - - def __init__(self, app: Flask, **kwargs: t.Any) -> None: - self.app = app - super().__init__(**kwargs) - - def invoke( # type: ignore - self, cli: t.Any = None, args: t.Any = None, **kwargs: t.Any - ) -> Result: - """Invokes a CLI command in an isolated environment. See - :meth:`CliRunner.invoke ` for - full method documentation. See :ref:`testing-cli` for examples. - - If the ``obj`` argument is not given, passes an instance of - :class:`~flask.cli.ScriptInfo` that knows how to load the Flask - app being tested. - - :param cli: Command object to invoke. Default is the app's - :attr:`~flask.app.Flask.cli` group. - :param args: List of strings to invoke the command with. - - :return: a :class:`~click.testing.Result` object. - """ - if cli is None: - cli = self.app.cli - - if "obj" not in kwargs: - kwargs["obj"] = ScriptInfo(create_app=lambda: self.app) - - return super().invoke(cli, args, **kwargs) diff --git a/serverenv/lib/python3.9/site-packages/flask/typing.py b/serverenv/lib/python3.9/site-packages/flask/typing.py deleted file mode 100644 index 6b70c40..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/typing.py +++ /dev/null @@ -1,93 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import typing as t - -if t.TYPE_CHECKING: # pragma: no cover - from _typeshed.wsgi import WSGIApplication # noqa: F401 - from werkzeug.datastructures import Headers # noqa: F401 - from werkzeug.sansio.response import Response # noqa: F401 - -# The possible types that are directly convertible or are a Response object. -ResponseValue = t.Union[ - "Response", - str, - bytes, - list[t.Any], - # Only dict is actually accepted, but Mapping allows for TypedDict. - t.Mapping[str, t.Any], - t.Iterator[str], - t.Iterator[bytes], - cabc.AsyncIterable[str], # for Quart, until App is generic. - cabc.AsyncIterable[bytes], -] - -# the possible types for an individual HTTP header -# This should be a Union, but mypy doesn't pass unless it's a TypeVar. -HeaderValue = t.Union[str, list[str], tuple[str, ...]] - -# the possible types for HTTP headers -HeadersValue = t.Union[ - "Headers", - t.Mapping[str, HeaderValue], - t.Sequence[tuple[str, HeaderValue]], -] - -# The possible types returned by a route function. -ResponseReturnValue = t.Union[ - ResponseValue, - tuple[ResponseValue, HeadersValue], - tuple[ResponseValue, int], - tuple[ResponseValue, int, HeadersValue], - "WSGIApplication", -] - -# Allow any subclass of werkzeug.Response, such as the one from Flask, -# as a callback argument. Using werkzeug.Response directly makes a -# callback annotated with flask.Response fail type checking. -ResponseClass = t.TypeVar("ResponseClass", bound="Response") - -AppOrBlueprintKey = t.Optional[str] # The App key is None, whereas blueprints are named -AfterRequestCallable = t.Union[ - t.Callable[[ResponseClass], ResponseClass], - t.Callable[[ResponseClass], t.Awaitable[ResponseClass]], -] -BeforeFirstRequestCallable = t.Union[ - t.Callable[[], None], t.Callable[[], t.Awaitable[None]] -] -BeforeRequestCallable = t.Union[ - t.Callable[[], t.Optional[ResponseReturnValue]], - t.Callable[[], t.Awaitable[t.Optional[ResponseReturnValue]]], -] -ShellContextProcessorCallable = t.Callable[[], dict[str, t.Any]] -TeardownCallable = t.Union[ - t.Callable[[t.Optional[BaseException]], None], - t.Callable[[t.Optional[BaseException]], t.Awaitable[None]], -] -TemplateContextProcessorCallable = t.Union[ - t.Callable[[], dict[str, t.Any]], - t.Callable[[], t.Awaitable[dict[str, t.Any]]], -] -TemplateFilterCallable = t.Callable[..., t.Any] -TemplateGlobalCallable = t.Callable[..., t.Any] -TemplateTestCallable = t.Callable[..., bool] -URLDefaultCallable = t.Callable[[str, dict[str, t.Any]], None] -URLValuePreprocessorCallable = t.Callable[ - [t.Optional[str], t.Optional[dict[str, t.Any]]], None -] - -# This should take Exception, but that either breaks typing the argument -# with a specific exception, or decorating multiple times with different -# exceptions (and using a union type on the argument). -# https://github.com/pallets/flask/issues/4095 -# https://github.com/pallets/flask/issues/4295 -# https://github.com/pallets/flask/issues/4297 -ErrorHandlerCallable = t.Union[ - t.Callable[[t.Any], ResponseReturnValue], - t.Callable[[t.Any], t.Awaitable[ResponseReturnValue]], -] - -RouteCallable = t.Union[ - t.Callable[..., ResponseReturnValue], - t.Callable[..., t.Awaitable[ResponseReturnValue]], -] diff --git a/serverenv/lib/python3.9/site-packages/flask/views.py b/serverenv/lib/python3.9/site-packages/flask/views.py deleted file mode 100644 index 53fe976..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/views.py +++ /dev/null @@ -1,191 +0,0 @@ -from __future__ import annotations - -import typing as t - -from . import typing as ft -from .globals import current_app -from .globals import request - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) - -http_method_funcs = frozenset( - ["get", "post", "head", "options", "delete", "put", "trace", "patch"] -) - - -class View: - """Subclass this class and override :meth:`dispatch_request` to - create a generic class-based view. Call :meth:`as_view` to create a - view function that creates an instance of the class with the given - arguments and calls its ``dispatch_request`` method with any URL - variables. - - See :doc:`views` for a detailed guide. - - .. code-block:: python - - class Hello(View): - init_every_request = False - - def dispatch_request(self, name): - return f"Hello, {name}!" - - app.add_url_rule( - "/hello/", view_func=Hello.as_view("hello") - ) - - Set :attr:`methods` on the class to change what methods the view - accepts. - - Set :attr:`decorators` on the class to apply a list of decorators to - the generated view function. Decorators applied to the class itself - will not be applied to the generated view function! - - Set :attr:`init_every_request` to ``False`` for efficiency, unless - you need to store request-global data on ``self``. - """ - - #: The methods this view is registered for. Uses the same default - #: (``["GET", "HEAD", "OPTIONS"]``) as ``route`` and - #: ``add_url_rule`` by default. - methods: t.ClassVar[t.Collection[str] | None] = None - - #: Control whether the ``OPTIONS`` method is handled automatically. - #: Uses the same default (``True``) as ``route`` and - #: ``add_url_rule`` by default. - provide_automatic_options: t.ClassVar[bool | None] = None - - #: A list of decorators to apply, in order, to the generated view - #: function. Remember that ``@decorator`` syntax is applied bottom - #: to top, so the first decorator in the list would be the bottom - #: decorator. - #: - #: .. versionadded:: 0.8 - decorators: t.ClassVar[list[t.Callable[..., t.Any]]] = [] - - #: Create a new instance of this view class for every request by - #: default. If a view subclass sets this to ``False``, the same - #: instance is used for every request. - #: - #: A single instance is more efficient, especially if complex setup - #: is done during init. However, storing data on ``self`` is no - #: longer safe across requests, and :data:`~flask.g` should be used - #: instead. - #: - #: .. versionadded:: 2.2 - init_every_request: t.ClassVar[bool] = True - - def dispatch_request(self) -> ft.ResponseReturnValue: - """The actual view function behavior. Subclasses must override - this and return a valid response. Any variables from the URL - rule are passed as keyword arguments. - """ - raise NotImplementedError() - - @classmethod - def as_view( - cls, name: str, *class_args: t.Any, **class_kwargs: t.Any - ) -> ft.RouteCallable: - """Convert the class into a view function that can be registered - for a route. - - By default, the generated view will create a new instance of the - view class for every request and call its - :meth:`dispatch_request` method. If the view class sets - :attr:`init_every_request` to ``False``, the same instance will - be used for every request. - - Except for ``name``, all other arguments passed to this method - are forwarded to the view class ``__init__`` method. - - .. versionchanged:: 2.2 - Added the ``init_every_request`` class attribute. - """ - if cls.init_every_request: - - def view(**kwargs: t.Any) -> ft.ResponseReturnValue: - self = view.view_class( # type: ignore[attr-defined] - *class_args, **class_kwargs - ) - return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] - - else: - self = cls(*class_args, **class_kwargs) # pyright: ignore - - def view(**kwargs: t.Any) -> ft.ResponseReturnValue: - return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] - - if cls.decorators: - view.__name__ = name - view.__module__ = cls.__module__ - for decorator in cls.decorators: - view = decorator(view) - - # We attach the view class to the view function for two reasons: - # first of all it allows us to easily figure out what class-based - # view this thing came from, secondly it's also used for instantiating - # the view class so you can actually replace it with something else - # for testing purposes and debugging. - view.view_class = cls # type: ignore - view.__name__ = name - view.__doc__ = cls.__doc__ - view.__module__ = cls.__module__ - view.methods = cls.methods # type: ignore - view.provide_automatic_options = cls.provide_automatic_options # type: ignore - return view - - -class MethodView(View): - """Dispatches request methods to the corresponding instance methods. - For example, if you implement a ``get`` method, it will be used to - handle ``GET`` requests. - - This can be useful for defining a REST API. - - :attr:`methods` is automatically set based on the methods defined on - the class. - - See :doc:`views` for a detailed guide. - - .. code-block:: python - - class CounterAPI(MethodView): - def get(self): - return str(session.get("counter", 0)) - - def post(self): - session["counter"] = session.get("counter", 0) + 1 - return redirect(url_for("counter")) - - app.add_url_rule( - "/counter", view_func=CounterAPI.as_view("counter") - ) - """ - - def __init_subclass__(cls, **kwargs: t.Any) -> None: - super().__init_subclass__(**kwargs) - - if "methods" not in cls.__dict__: - methods = set() - - for base in cls.__bases__: - if getattr(base, "methods", None): - methods.update(base.methods) # type: ignore[attr-defined] - - for key in http_method_funcs: - if hasattr(cls, key): - methods.add(key.upper()) - - if methods: - cls.methods = methods - - def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue: - meth = getattr(self, request.method.lower(), None) - - # If the request method is HEAD and we don't have a handler for it - # retry with GET. - if meth is None and request.method == "HEAD": - meth = getattr(self, "get", None) - - assert meth is not None, f"Unimplemented method {request.method!r}" - return current_app.ensure_sync(meth)(**kwargs) # type: ignore[no-any-return] diff --git a/serverenv/lib/python3.9/site-packages/flask/wrappers.py b/serverenv/lib/python3.9/site-packages/flask/wrappers.py deleted file mode 100644 index bab6102..0000000 --- a/serverenv/lib/python3.9/site-packages/flask/wrappers.py +++ /dev/null @@ -1,257 +0,0 @@ -from __future__ import annotations - -import typing as t - -from werkzeug.exceptions import BadRequest -from werkzeug.exceptions import HTTPException -from werkzeug.wrappers import Request as RequestBase -from werkzeug.wrappers import Response as ResponseBase - -from . import json -from .globals import current_app -from .helpers import _split_blueprint_path - -if t.TYPE_CHECKING: # pragma: no cover - from werkzeug.routing import Rule - - -class Request(RequestBase): - """The request object used by default in Flask. Remembers the - matched endpoint and view arguments. - - It is what ends up as :class:`~flask.request`. If you want to replace - the request object used you can subclass this and set - :attr:`~flask.Flask.request_class` to your subclass. - - The request object is a :class:`~werkzeug.wrappers.Request` subclass and - provides all of the attributes Werkzeug defines plus a few Flask - specific ones. - """ - - json_module: t.Any = json - - #: The internal URL rule that matched the request. This can be - #: useful to inspect which methods are allowed for the URL from - #: a before/after handler (``request.url_rule.methods``) etc. - #: Though if the request's method was invalid for the URL rule, - #: the valid list is available in ``routing_exception.valid_methods`` - #: instead (an attribute of the Werkzeug exception - #: :exc:`~werkzeug.exceptions.MethodNotAllowed`) - #: because the request was never internally bound. - #: - #: .. versionadded:: 0.6 - url_rule: Rule | None = None - - #: A dict of view arguments that matched the request. If an exception - #: happened when matching, this will be ``None``. - view_args: dict[str, t.Any] | None = None - - #: If matching the URL failed, this is the exception that will be - #: raised / was raised as part of the request handling. This is - #: usually a :exc:`~werkzeug.exceptions.NotFound` exception or - #: something similar. - routing_exception: HTTPException | None = None - - _max_content_length: int | None = None - _max_form_memory_size: int | None = None - _max_form_parts: int | None = None - - @property - def max_content_length(self) -> int | None: - """The maximum number of bytes that will be read during this request. If - this limit is exceeded, a 413 :exc:`~werkzeug.exceptions.RequestEntityTooLarge` - error is raised. If it is set to ``None``, no limit is enforced at the - Flask application level. However, if it is ``None`` and the request has - no ``Content-Length`` header and the WSGI server does not indicate that - it terminates the stream, then no data is read to avoid an infinite - stream. - - Each request defaults to the :data:`MAX_CONTENT_LENGTH` config, which - defaults to ``None``. It can be set on a specific ``request`` to apply - the limit to that specific view. This should be set appropriately based - on an application's or view's specific needs. - - .. versionchanged:: 3.1 - This can be set per-request. - - .. versionchanged:: 0.6 - This is configurable through Flask config. - """ - if self._max_content_length is not None: - return self._max_content_length - - if not current_app: - return super().max_content_length - - return current_app.config["MAX_CONTENT_LENGTH"] # type: ignore[no-any-return] - - @max_content_length.setter - def max_content_length(self, value: int | None) -> None: - self._max_content_length = value - - @property - def max_form_memory_size(self) -> int | None: - """The maximum size in bytes any non-file form field may be in a - ``multipart/form-data`` body. If this limit is exceeded, a 413 - :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it - is set to ``None``, no limit is enforced at the Flask application level. - - Each request defaults to the :data:`MAX_FORM_MEMORY_SIZE` config, which - defaults to ``500_000``. It can be set on a specific ``request`` to - apply the limit to that specific view. This should be set appropriately - based on an application's or view's specific needs. - - .. versionchanged:: 3.1 - This is configurable through Flask config. - """ - if self._max_form_memory_size is not None: - return self._max_form_memory_size - - if not current_app: - return super().max_form_memory_size - - return current_app.config["MAX_FORM_MEMORY_SIZE"] # type: ignore[no-any-return] - - @max_form_memory_size.setter - def max_form_memory_size(self, value: int | None) -> None: - self._max_form_memory_size = value - - @property # type: ignore[override] - def max_form_parts(self) -> int | None: - """The maximum number of fields that may be present in a - ``multipart/form-data`` body. If this limit is exceeded, a 413 - :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it - is set to ``None``, no limit is enforced at the Flask application level. - - Each request defaults to the :data:`MAX_FORM_PARTS` config, which - defaults to ``1_000``. It can be set on a specific ``request`` to apply - the limit to that specific view. This should be set appropriately based - on an application's or view's specific needs. - - .. versionchanged:: 3.1 - This is configurable through Flask config. - """ - if self._max_form_parts is not None: - return self._max_form_parts - - if not current_app: - return super().max_form_parts - - return current_app.config["MAX_FORM_PARTS"] # type: ignore[no-any-return] - - @max_form_parts.setter - def max_form_parts(self, value: int | None) -> None: - self._max_form_parts = value - - @property - def endpoint(self) -> str | None: - """The endpoint that matched the request URL. - - This will be ``None`` if matching failed or has not been - performed yet. - - This in combination with :attr:`view_args` can be used to - reconstruct the same URL or a modified URL. - """ - if self.url_rule is not None: - return self.url_rule.endpoint # type: ignore[no-any-return] - - return None - - @property - def blueprint(self) -> str | None: - """The registered name of the current blueprint. - - This will be ``None`` if the endpoint is not part of a - blueprint, or if URL matching failed or has not been performed - yet. - - This does not necessarily match the name the blueprint was - created with. It may have been nested, or registered with a - different name. - """ - endpoint = self.endpoint - - if endpoint is not None and "." in endpoint: - return endpoint.rpartition(".")[0] - - return None - - @property - def blueprints(self) -> list[str]: - """The registered names of the current blueprint upwards through - parent blueprints. - - This will be an empty list if there is no current blueprint, or - if URL matching failed. - - .. versionadded:: 2.0.1 - """ - name = self.blueprint - - if name is None: - return [] - - return _split_blueprint_path(name) - - def _load_form_data(self) -> None: - super()._load_form_data() - - # In debug mode we're replacing the files multidict with an ad-hoc - # subclass that raises a different error for key errors. - if ( - current_app - and current_app.debug - and self.mimetype != "multipart/form-data" - and not self.files - ): - from .debughelpers import attach_enctype_error_multidict - - attach_enctype_error_multidict(self) - - def on_json_loading_failed(self, e: ValueError | None) -> t.Any: - try: - return super().on_json_loading_failed(e) - except BadRequest as ebr: - if current_app and current_app.debug: - raise - - raise BadRequest() from ebr - - -class Response(ResponseBase): - """The response object that is used by default in Flask. Works like the - response object from Werkzeug but is set to have an HTML mimetype by - default. Quite often you don't have to create this object yourself because - :meth:`~flask.Flask.make_response` will take care of that for you. - - If you want to replace the response object used you can subclass this and - set :attr:`~flask.Flask.response_class` to your subclass. - - .. versionchanged:: 1.0 - JSON support is added to the response, like the request. This is useful - when testing to get the test client response data as JSON. - - .. versionchanged:: 1.0 - - Added :attr:`max_cookie_size`. - """ - - default_mimetype: str | None = "text/html" - - json_module = json - - autocorrect_location_header = False - - @property - def max_cookie_size(self) -> int: # type: ignore - """Read-only view of the :data:`MAX_COOKIE_SIZE` config key. - - See :attr:`~werkzeug.wrappers.Response.max_cookie_size` in - Werkzeug's docs. - """ - if current_app: - return current_app.config["MAX_COOKIE_SIZE"] # type: ignore[no-any-return] - - # return Werkzeug's default when not in an app context - return super().max_cookie_size diff --git a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/METADATA deleted file mode 100644 index 8a2f639..0000000 --- a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/METADATA +++ /dev/null @@ -1,202 +0,0 @@ -Metadata-Version: 2.4 -Name: h11 -Version: 0.16.0 -Summary: A pure-Python, bring-your-own-I/O implementation of HTTP/1.1 -Home-page: https://github.com/python-hyper/h11 -Author: Nathaniel J. Smith -Author-email: njs@pobox.com -License: MIT -Classifier: Development Status :: 3 - Alpha -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Topic :: Internet :: WWW/HTTP -Classifier: Topic :: System :: Networking -Requires-Python: >=3.8 -License-File: LICENSE.txt -Dynamic: author -Dynamic: author-email -Dynamic: classifier -Dynamic: description -Dynamic: home-page -Dynamic: license -Dynamic: license-file -Dynamic: requires-python -Dynamic: summary - -h11 -=== - -.. image:: https://travis-ci.org/python-hyper/h11.svg?branch=master - :target: https://travis-ci.org/python-hyper/h11 - :alt: Automated test status - -.. image:: https://codecov.io/gh/python-hyper/h11/branch/master/graph/badge.svg - :target: https://codecov.io/gh/python-hyper/h11 - :alt: Test coverage - -.. image:: https://readthedocs.org/projects/h11/badge/?version=latest - :target: http://h11.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status - -This is a little HTTP/1.1 library written from scratch in Python, -heavily inspired by `hyper-h2 `_. - -It's a "bring-your-own-I/O" library; h11 contains no IO code -whatsoever. This means you can hook h11 up to your favorite network -API, and that could be anything you want: synchronous, threaded, -asynchronous, or your own implementation of `RFC 6214 -`_ -- h11 won't judge you. -(Compare this to the current state of the art, where every time a `new -network API `_ comes along then someone -gets to start over reimplementing the entire HTTP protocol from -scratch.) Cory Benfield made an `excellent blog post describing the -benefits of this approach -`_, or if you like video -then here's his `PyCon 2016 talk on the same theme -`_. - -This also means that h11 is not immediately useful out of the box: -it's a toolkit for building programs that speak HTTP, not something -that could directly replace ``requests`` or ``twisted.web`` or -whatever. But h11 makes it much easier to implement something like -``requests`` or ``twisted.web``. - -At a high level, working with h11 goes like this: - -1) First, create an ``h11.Connection`` object to track the state of a - single HTTP/1.1 connection. - -2) When you read data off the network, pass it to - ``conn.receive_data(...)``; you'll get back a list of objects - representing high-level HTTP "events". - -3) When you want to send a high-level HTTP event, create the - corresponding "event" object and pass it to ``conn.send(...)``; - this will give you back some bytes that you can then push out - through the network. - -For example, a client might instantiate and then send a -``h11.Request`` object, then zero or more ``h11.Data`` objects for the -request body (e.g., if this is a POST), and then a -``h11.EndOfMessage`` to indicate the end of the message. Then the -server would then send back a ``h11.Response``, some ``h11.Data``, and -its own ``h11.EndOfMessage``. If either side violates the protocol, -you'll get a ``h11.ProtocolError`` exception. - -h11 is suitable for implementing both servers and clients, and has a -pleasantly symmetric API: the events you send as a client are exactly -the ones that you receive as a server and vice-versa. - -`Here's an example of a tiny HTTP client -`_ - -It also has `a fine manual `_. - -FAQ ---- - -*Whyyyyy?* - -I wanted to play with HTTP in `Curio -`__ and `Trio -`__, which at the time didn't have any -HTTP libraries. So I thought, no big deal, Python has, like, a dozen -different implementations of HTTP, surely I can find one that's -reusable. I didn't find one, but I did find Cory's call-to-arms -blog-post. So I figured, well, fine, if I have to implement HTTP from -scratch, at least I can make sure no-one *else* has to ever again. - -*Should I use it?* - -Maybe. You should be aware that it's a very young project. But, it's -feature complete and has an exhaustive test-suite and complete docs, -so the next step is for people to try using it and see how it goes -:-). If you do then please let us know -- if nothing else we'll want -to talk to you before making any incompatible changes! - -*What are the features/limitations?* - -Roughly speaking, it's trying to be a robust, complete, and non-hacky -implementation of the first "chapter" of the HTTP/1.1 spec: `RFC 7230: -HTTP/1.1 Message Syntax and Routing -`_. That is, it mostly focuses on -implementing HTTP at the level of taking bytes on and off the wire, -and the headers related to that, and tries to be anal about spec -conformance. It doesn't know about higher-level concerns like URL -routing, conditional GETs, cross-origin cookie policies, or content -negotiation. But it does know how to take care of framing, -cross-version differences in keep-alive handling, and the "obsolete -line folding" rule, so you can focus your energies on the hard / -interesting parts for your application, and it tries to support the -full specification in the sense that any useful HTTP/1.1 conformant -application should be able to use h11. - -It's pure Python, and has no dependencies outside of the standard -library. - -It has a test suite with 100.0% coverage for both statements and -branches. - -Currently it supports Python 3 (testing on 3.8-3.12) and PyPy 3. -The last Python 2-compatible version was h11 0.11.x. -(Originally it had a Cython wrapper for `http-parser -`_ and a beautiful nested state -machine implemented with ``yield from`` to postprocess the output. But -I had to take these out -- the new *parser* needs fewer lines-of-code -than the old *parser wrapper*, is written in pure Python, uses no -exotic language syntax, and has more features. It's sad, really; that -old state machine was really slick. I just need a few sentences here -to mourn that.) - -I don't know how fast it is. I haven't benchmarked or profiled it yet, -so it's probably got a few pointless hot spots, and I've been trying -to err on the side of simplicity and robustness instead of -micro-optimization. But at the architectural level I tried hard to -avoid fundamentally bad decisions, e.g., I believe that all the -parsing algorithms remain linear-time even in the face of pathological -input like slowloris, and there are no byte-by-byte loops. (I also -believe that it maintains bounded memory usage in the face of -arbitrary/pathological input.) - -The whole library is ~800 lines-of-code. You can read and understand -the whole thing in less than an hour. Most of the energy invested in -this so far has been spent on trying to keep things simple by -minimizing special-cases and ad hoc state manipulation; even though it -is now quite small and simple, I'm still annoyed that I haven't -figured out how to make it even smaller and simpler. (Unfortunately, -HTTP does not lend itself to simplicity.) - -The API is ~feature complete and I don't expect the general outlines -to change much, but you can't judge an API's ergonomics until you -actually document and use it, so I'd expect some changes in the -details. - -*How do I try it?* - -.. code-block:: sh - - $ pip install h11 - $ git clone git@github.com:python-hyper/h11 - $ cd h11/examples - $ python basic-client.py - -and go from there. - -*License?* - -MIT - -*Code of conduct?* - -Contributors are requested to follow our `code of conduct -`_ in -all project spaces. diff --git a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/RECORD deleted file mode 100644 index e52330f..0000000 --- a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/RECORD +++ /dev/null @@ -1,29 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_abnf.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_connection.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_events.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_headers.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_readers.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_receivebuffer.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_state.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_util.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_version.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h11/_writers.cpython-39.pyc,, -h11-0.16.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -h11-0.16.0.dist-info/METADATA,sha256=KPMmCYrAn8unm48YD5YIfIQf4kViFct7hyqcfVzRnWQ,8348 -h11-0.16.0.dist-info/RECORD,, -h11-0.16.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91 -h11-0.16.0.dist-info/licenses/LICENSE.txt,sha256=N9tbuFkm2yikJ6JYZ_ELEjIAOuob5pzLhRE4rbjm82E,1124 -h11-0.16.0.dist-info/top_level.txt,sha256=F7dC4jl3zeh8TGHEPaWJrMbeuoWbS379Gwdi-Yvdcis,4 -h11/__init__.py,sha256=iO1KzkSO42yZ6ffg-VMgbx_ZVTWGUY00nRYEWn-s3kY,1507 -h11/_abnf.py,sha256=ybixr0xsupnkA6GFAyMubuXF6Tc1lb_hF890NgCsfNc,4815 -h11/_connection.py,sha256=k9YRVf6koZqbttBW36xSWaJpWdZwa-xQVU9AHEo9DuI,26863 -h11/_events.py,sha256=I97aXoal1Wu7dkL548BANBUCkOIbe-x5CioYA9IBY14,11792 -h11/_headers.py,sha256=P7D-lBNxHwdLZPLimmYwrPG-9ZkjElvvJZJdZAgSP-4,10412 -h11/_readers.py,sha256=a4RypORUCC3d0q_kxPuBIM7jTD8iLt5X91TH0FsduN4,8590 -h11/_receivebuffer.py,sha256=xrspsdsNgWFxRfQcTXxR8RrdjRXXTK0Io5cQYWpJ1Ws,5252 -h11/_state.py,sha256=_5LG_BGR8FCcFQeBPH-TMHgm_-B-EUcWCnQof_9XjFE,13231 -h11/_util.py,sha256=LWkkjXyJaFlAy6Lt39w73UStklFT5ovcvo0TkY7RYuk,4888 -h11/_version.py,sha256=GVSsbPSPDcOuF6ptfIiXnVJoaEm3ygXbMnqlr_Giahw,686 -h11/_writers.py,sha256=oFKm6PtjeHfbj4RLX7VB7KDc1gIY53gXG3_HR9ltmTA,5081 -h11/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 diff --git a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/WHEEL deleted file mode 100644 index 1eb3c49..0000000 --- a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (78.1.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt b/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt deleted file mode 100644 index 8f080ea..0000000 --- a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/licenses/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/top_level.txt b/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/top_level.txt deleted file mode 100644 index 0d24def..0000000 --- a/serverenv/lib/python3.9/site-packages/h11-0.16.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -h11 diff --git a/serverenv/lib/python3.9/site-packages/h11/__init__.py b/serverenv/lib/python3.9/site-packages/h11/__init__.py deleted file mode 100644 index 989e92c..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/__init__.py +++ /dev/null @@ -1,62 +0,0 @@ -# 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/serverenv/lib/python3.9/site-packages/h11/_abnf.py b/serverenv/lib/python3.9/site-packages/h11/_abnf.py deleted file mode 100644 index 933587f..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_abnf.py +++ /dev/null @@ -1,132 +0,0 @@ -# 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"{OWS}\r\n".format( - **globals() - ) # Even though the specification does not allow for extra whitespaces, - # we are lenient with trailing whitespaces because some servers on the wild use it. -) diff --git a/serverenv/lib/python3.9/site-packages/h11/_connection.py b/serverenv/lib/python3.9/site-packages/h11/_connection.py deleted file mode 100644 index e37d82a..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_connection.py +++ /dev/null @@ -1,659 +0,0 @@ -# This contains the main Connection class. Everything in h11 revolves around -# this. -from typing import ( - Any, - Callable, - cast, - Dict, - List, - Optional, - overload, - Tuple, - Type, - Union, -) - -from ._events import ( - ConnectionClosed, - Data, - EndOfMessage, - Event, - InformationalResponse, - Request, - Response, -) -from ._headers import get_comma_header, has_expect_100_continue, set_comma_header -from ._readers import READERS, ReadersType -from ._receivebuffer import ReceiveBuffer -from ._state import ( - _SWITCH_CONNECT, - _SWITCH_UPGRADE, - CLIENT, - ConnectionState, - DONE, - ERROR, - MIGHT_SWITCH_PROTOCOL, - SEND_BODY, - SERVER, - SWITCHED_PROTOCOL, -) -from ._util import ( # Import the internal things we need - LocalProtocolError, - RemoteProtocolError, - Sentinel, -) -from ._writers import WRITERS, WritersType - -# Everything in __all__ gets re-exported as part of the h11 public API. -__all__ = ["Connection", "NEED_DATA", "PAUSED"] - - -class NEED_DATA(Sentinel, metaclass=Sentinel): - pass - - -class PAUSED(Sentinel, metaclass=Sentinel): - pass - - -# If we ever have this much buffered without it making a complete parseable -# event, we error out. The only time we really buffer is when reading the -# request/response line + headers together, so this is effectively the limit on -# the size of that. -# -# Some precedents for defaults: -# - node.js: 80 * 1024 -# - tomcat: 8 * 1024 -# - IIS: 16 * 1024 -# - Apache: <8 KiB per line> -DEFAULT_MAX_INCOMPLETE_EVENT_SIZE = 16 * 1024 - - -# RFC 7230's rules for connection lifecycles: -# - If either side says they want to close the connection, then the connection -# must close. -# - HTTP/1.1 defaults to keep-alive unless someone says Connection: close -# - HTTP/1.0 defaults to close unless both sides say Connection: keep-alive -# (and even this is a mess -- e.g. if you're implementing a proxy then -# sending Connection: keep-alive is forbidden). -# -# We simplify life by simply not supporting keep-alive with HTTP/1.0 peers. So -# our rule is: -# - If someone says Connection: close, we will close -# - If someone uses HTTP/1.0, we will close. -def _keep_alive(event: Union[Request, Response]) -> bool: - connection = get_comma_header(event.headers, b"connection") - if b"close" in connection: - return False - if getattr(event, "http_version", b"1.1") < b"1.1": - return False - return True - - -def _body_framing( - request_method: bytes, event: Union[Request, Response] -) -> Tuple[str, Union[Tuple[()], Tuple[int]]]: - # Called when we enter SEND_BODY to figure out framing information for - # this body. - # - # These are the only two events that can trigger a SEND_BODY state: - assert type(event) in (Request, Response) - # Returns one of: - # - # ("content-length", count) - # ("chunked", ()) - # ("http/1.0", ()) - # - # which are (lookup key, *args) for constructing body reader/writer - # objects. - # - # Reference: https://tools.ietf.org/html/rfc7230#section-3.3.3 - # - # Step 1: some responses always have an empty body, regardless of what the - # headers say. - if type(event) is Response: - if ( - event.status_code in (204, 304) - or request_method == b"HEAD" - or (request_method == b"CONNECT" and 200 <= event.status_code < 300) - ): - return ("content-length", (0,)) - # Section 3.3.3 also lists another case -- responses with status_code - # < 200. For us these are InformationalResponses, not Responses, so - # they can't get into this function in the first place. - assert event.status_code >= 200 - - # Step 2: check for Transfer-Encoding (T-E beats C-L): - transfer_encodings = get_comma_header(event.headers, b"transfer-encoding") - if transfer_encodings: - assert transfer_encodings == [b"chunked"] - return ("chunked", ()) - - # Step 3: check for Content-Length - content_lengths = get_comma_header(event.headers, b"content-length") - if content_lengths: - return ("content-length", (int(content_lengths[0]),)) - - # Step 4: no applicable headers; fallback/default depends on type - if type(event) is Request: - return ("content-length", (0,)) - else: - return ("http/1.0", ()) - - -################################################################ -# -# The main Connection class -# -################################################################ - - -class Connection: - """An object encapsulating the state of an HTTP connection. - - Args: - our_role: If you're implementing a client, pass :data:`h11.CLIENT`. If - you're implementing a server, pass :data:`h11.SERVER`. - - max_incomplete_event_size (int): - The maximum number of bytes we're willing to buffer of an - incomplete event. In practice this mostly sets a limit on the - maximum size of the request/response line + headers. If this is - exceeded, then :meth:`next_event` will raise - :exc:`RemoteProtocolError`. - - """ - - def __init__( - self, - our_role: Type[Sentinel], - max_incomplete_event_size: int = DEFAULT_MAX_INCOMPLETE_EVENT_SIZE, - ) -> None: - self._max_incomplete_event_size = max_incomplete_event_size - # State and role tracking - if our_role not in (CLIENT, SERVER): - raise ValueError(f"expected CLIENT or SERVER, not {our_role!r}") - self.our_role = our_role - self.their_role: Type[Sentinel] - if our_role is CLIENT: - self.their_role = SERVER - else: - self.their_role = CLIENT - self._cstate = ConnectionState() - - # Callables for converting data->events or vice-versa given the - # current state - self._writer = self._get_io_object(self.our_role, None, WRITERS) - self._reader = self._get_io_object(self.their_role, None, READERS) - - # Holds any unprocessed received data - self._receive_buffer = ReceiveBuffer() - # If this is true, then it indicates that the incoming connection was - # closed *after* the end of whatever's in self._receive_buffer: - self._receive_buffer_closed = False - - # Extra bits of state that don't fit into the state machine. - # - # These two are only used to interpret framing headers for figuring - # out how to read/write response bodies. their_http_version is also - # made available as a convenient public API. - self.their_http_version: Optional[bytes] = None - self._request_method: Optional[bytes] = None - # This is pure flow-control and doesn't at all affect the set of legal - # transitions, so no need to bother ConnectionState with it: - self.client_is_waiting_for_100_continue = False - - @property - def states(self) -> Dict[Type[Sentinel], Type[Sentinel]]: - """A dictionary like:: - - {CLIENT: , SERVER: } - - See :ref:`state-machine` for details. - - """ - return dict(self._cstate.states) - - @property - def our_state(self) -> Type[Sentinel]: - """The current state of whichever role we are playing. See - :ref:`state-machine` for details. - """ - return self._cstate.states[self.our_role] - - @property - def their_state(self) -> Type[Sentinel]: - """The current state of whichever role we are NOT playing. See - :ref:`state-machine` for details. - """ - return self._cstate.states[self.their_role] - - @property - def they_are_waiting_for_100_continue(self) -> bool: - return self.their_role is CLIENT and self.client_is_waiting_for_100_continue - - def start_next_cycle(self) -> None: - """Attempt to reset our connection state for a new request/response - cycle. - - If both client and server are in :data:`DONE` state, then resets them - both to :data:`IDLE` state in preparation for a new request/response - cycle on this same connection. Otherwise, raises a - :exc:`LocalProtocolError`. - - See :ref:`keepalive-and-pipelining`. - - """ - old_states = dict(self._cstate.states) - self._cstate.start_next_cycle() - self._request_method = None - # self.their_http_version gets left alone, since it presumably lasts - # beyond a single request/response cycle - assert not self.client_is_waiting_for_100_continue - self._respond_to_state_changes(old_states) - - def _process_error(self, role: Type[Sentinel]) -> None: - old_states = dict(self._cstate.states) - self._cstate.process_error(role) - self._respond_to_state_changes(old_states) - - def _server_switch_event(self, event: Event) -> Optional[Type[Sentinel]]: - if type(event) is InformationalResponse and event.status_code == 101: - return _SWITCH_UPGRADE - if type(event) is Response: - if ( - _SWITCH_CONNECT in self._cstate.pending_switch_proposals - and 200 <= event.status_code < 300 - ): - return _SWITCH_CONNECT - return None - - # All events go through here - def _process_event(self, role: Type[Sentinel], event: Event) -> None: - # First, pass the event through the state machine to make sure it - # succeeds. - old_states = dict(self._cstate.states) - if role is CLIENT and type(event) is Request: - if event.method == b"CONNECT": - self._cstate.process_client_switch_proposal(_SWITCH_CONNECT) - if get_comma_header(event.headers, b"upgrade"): - self._cstate.process_client_switch_proposal(_SWITCH_UPGRADE) - server_switch_event = None - if role is SERVER: - server_switch_event = self._server_switch_event(event) - self._cstate.process_event(role, type(event), server_switch_event) - - # Then perform the updates triggered by it. - - if type(event) is Request: - self._request_method = event.method - - if role is self.their_role and type(event) in ( - Request, - Response, - InformationalResponse, - ): - event = cast(Union[Request, Response, InformationalResponse], event) - self.their_http_version = event.http_version - - # Keep alive handling - # - # RFC 7230 doesn't really say what one should do if Connection: close - # shows up on a 1xx InformationalResponse. I think the idea is that - # this is not supposed to happen. In any case, if it does happen, we - # ignore it. - if type(event) in (Request, Response) and not _keep_alive( - cast(Union[Request, Response], event) - ): - self._cstate.process_keep_alive_disabled() - - # 100-continue - if type(event) is Request and has_expect_100_continue(event): - self.client_is_waiting_for_100_continue = True - if type(event) in (InformationalResponse, Response): - self.client_is_waiting_for_100_continue = False - if role is CLIENT and type(event) in (Data, EndOfMessage): - self.client_is_waiting_for_100_continue = False - - self._respond_to_state_changes(old_states, event) - - def _get_io_object( - self, - role: Type[Sentinel], - event: Optional[Event], - io_dict: Union[ReadersType, WritersType], - ) -> Optional[Callable[..., Any]]: - # event may be None; it's only used when entering SEND_BODY - state = self._cstate.states[role] - if state is SEND_BODY: - # Special case: the io_dict has a dict of reader/writer factories - # that depend on the request/response framing. - framing_type, args = _body_framing( - cast(bytes, self._request_method), cast(Union[Request, Response], event) - ) - return io_dict[SEND_BODY][framing_type](*args) # type: ignore[index] - else: - # General case: the io_dict just has the appropriate reader/writer - # for this state - return io_dict.get((role, state)) # type: ignore[return-value] - - # This must be called after any action that might have caused - # self._cstate.states to change. - def _respond_to_state_changes( - self, - old_states: Dict[Type[Sentinel], Type[Sentinel]], - event: Optional[Event] = None, - ) -> None: - # Update reader/writer - if self.our_state != old_states[self.our_role]: - self._writer = self._get_io_object(self.our_role, event, WRITERS) - if self.their_state != old_states[self.their_role]: - self._reader = self._get_io_object(self.their_role, event, READERS) - - @property - def trailing_data(self) -> Tuple[bytes, bool]: - """Data that has been received, but not yet processed, represented as - a tuple with two elements, where the first is a byte-string containing - the unprocessed data itself, and the second is a bool that is True if - the receive connection was closed. - - See :ref:`switching-protocols` for discussion of why you'd want this. - """ - return (bytes(self._receive_buffer), self._receive_buffer_closed) - - def receive_data(self, data: bytes) -> None: - """Add data to our internal receive buffer. - - This does not actually do any processing on the data, just stores - it. To trigger processing, you have to call :meth:`next_event`. - - Args: - data (:term:`bytes-like object`): - The new data that was just received. - - Special case: If *data* is an empty byte-string like ``b""``, - then this indicates that the remote side has closed the - connection (end of file). Normally this is convenient, because - standard Python APIs like :meth:`file.read` or - :meth:`socket.recv` use ``b""`` to indicate end-of-file, while - other failures to read are indicated using other mechanisms - like raising :exc:`TimeoutError`. When using such an API you - can just blindly pass through whatever you get from ``read`` - to :meth:`receive_data`, and everything will work. - - But, if you have an API where reading an empty string is a - valid non-EOF condition, then you need to be aware of this and - make sure to check for such strings and avoid passing them to - :meth:`receive_data`. - - Returns: - Nothing, but after calling this you should call :meth:`next_event` - to parse the newly received data. - - Raises: - RuntimeError: - Raised if you pass an empty *data*, indicating EOF, and then - pass a non-empty *data*, indicating more data that somehow - arrived after the EOF. - - (Calling ``receive_data(b"")`` multiple times is fine, - and equivalent to calling it once.) - - """ - if data: - if self._receive_buffer_closed: - raise RuntimeError("received close, then received more data?") - self._receive_buffer += data - else: - self._receive_buffer_closed = True - - def _extract_next_receive_event( - self, - ) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]: - state = self.their_state - # We don't pause immediately when they enter DONE, because even in - # DONE state we can still process a ConnectionClosed() event. But - # if we have data in our buffer, then we definitely aren't getting - # a ConnectionClosed() immediately and we need to pause. - if state is DONE and self._receive_buffer: - return PAUSED - if state is MIGHT_SWITCH_PROTOCOL or state is SWITCHED_PROTOCOL: - return PAUSED - assert self._reader is not None - event = self._reader(self._receive_buffer) - if event is None: - if not self._receive_buffer and self._receive_buffer_closed: - # In some unusual cases (basically just HTTP/1.0 bodies), EOF - # triggers an actual protocol event; in that case, we want to - # return that event, and then the state will change and we'll - # get called again to generate the actual ConnectionClosed(). - if hasattr(self._reader, "read_eof"): - event = self._reader.read_eof() - else: - event = ConnectionClosed() - if event is None: - event = NEED_DATA - return event # type: ignore[no-any-return] - - def next_event(self) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]: - """Parse the next event out of our receive buffer, update our internal - state, and return it. - - This is a mutating operation -- think of it like calling :func:`next` - on an iterator. - - Returns: - : One of three things: - - 1) An event object -- see :ref:`events`. - - 2) The special constant :data:`NEED_DATA`, which indicates that - you need to read more data from your socket and pass it to - :meth:`receive_data` before this method will be able to return - any more events. - - 3) The special constant :data:`PAUSED`, which indicates that we - are not in a state where we can process incoming data (usually - because the peer has finished their part of the current - request/response cycle, and you have not yet called - :meth:`start_next_cycle`). See :ref:`flow-control` for details. - - Raises: - RemoteProtocolError: - The peer has misbehaved. You should close the connection - (possibly after sending some kind of 4xx response). - - Once this method returns :class:`ConnectionClosed` once, then all - subsequent calls will also return :class:`ConnectionClosed`. - - If this method raises any exception besides :exc:`RemoteProtocolError` - then that's a bug -- if it happens please file a bug report! - - If this method raises any exception then it also sets - :attr:`Connection.their_state` to :data:`ERROR` -- see - :ref:`error-handling` for discussion. - - """ - - if self.their_state is ERROR: - raise RemoteProtocolError("Can't receive data when peer state is ERROR") - try: - event = self._extract_next_receive_event() - if event not in [NEED_DATA, PAUSED]: - self._process_event(self.their_role, cast(Event, event)) - if event is NEED_DATA: - if len(self._receive_buffer) > self._max_incomplete_event_size: - # 431 is "Request header fields too large" which is pretty - # much the only situation where we can get here - raise RemoteProtocolError( - "Receive buffer too long", error_status_hint=431 - ) - if self._receive_buffer_closed: - # We're still trying to complete some event, but that's - # never going to happen because no more data is coming - raise RemoteProtocolError("peer unexpectedly closed connection") - return event - except BaseException as exc: - self._process_error(self.their_role) - if isinstance(exc, LocalProtocolError): - exc._reraise_as_remote_protocol_error() - else: - raise - - @overload - def send(self, event: ConnectionClosed) -> None: - ... - - @overload - def send( - self, event: Union[Request, InformationalResponse, Response, Data, EndOfMessage] - ) -> bytes: - ... - - @overload - def send(self, event: Event) -> Optional[bytes]: - ... - - def send(self, event: Event) -> Optional[bytes]: - """Convert a high-level event into bytes that can be sent to the peer, - while updating our internal state machine. - - Args: - event: The :ref:`event ` to send. - - Returns: - If ``type(event) is ConnectionClosed``, then returns - ``None``. Otherwise, returns a :term:`bytes-like object`. - - Raises: - LocalProtocolError: - Sending this event at this time would violate our - understanding of the HTTP/1.1 protocol. - - If this method raises any exception then it also sets - :attr:`Connection.our_state` to :data:`ERROR` -- see - :ref:`error-handling` for discussion. - - """ - data_list = self.send_with_data_passthrough(event) - if data_list is None: - return None - else: - return b"".join(data_list) - - def send_with_data_passthrough(self, event: Event) -> Optional[List[bytes]]: - """Identical to :meth:`send`, except that in situations where - :meth:`send` returns a single :term:`bytes-like object`, this instead - returns a list of them -- and when sending a :class:`Data` event, this - list is guaranteed to contain the exact object you passed in as - :attr:`Data.data`. See :ref:`sendfile` for discussion. - - """ - if self.our_state is ERROR: - raise LocalProtocolError("Can't send data when our state is ERROR") - try: - if type(event) is Response: - event = self._clean_up_response_headers_for_sending(event) - # We want to call _process_event before calling the writer, - # because if someone tries to do something invalid then this will - # give a sensible error message, while our writers all just assume - # they will only receive valid events. But, _process_event might - # change self._writer. So we have to do a little dance: - writer = self._writer - self._process_event(self.our_role, event) - if type(event) is ConnectionClosed: - return None - else: - # In any situation where writer is None, process_event should - # have raised ProtocolError - assert writer is not None - data_list: List[bytes] = [] - writer(event, data_list.append) - return data_list - except: - self._process_error(self.our_role) - raise - - def send_failed(self) -> None: - """Notify the state machine that we failed to send the data it gave - us. - - This causes :attr:`Connection.our_state` to immediately become - :data:`ERROR` -- see :ref:`error-handling` for discussion. - - """ - self._process_error(self.our_role) - - # When sending a Response, we take responsibility for a few things: - # - # - Sometimes you MUST set Connection: close. We take care of those - # times. (You can also set it yourself if you want, and if you do then - # we'll respect that and close the connection at the right time. But you - # don't have to worry about that unless you want to.) - # - # - The user has to set Content-Length if they want it. Otherwise, for - # responses that have bodies (e.g. not HEAD), then we will automatically - # select the right mechanism for streaming a body of unknown length, - # which depends on depending on the peer's HTTP version. - # - # This function's *only* responsibility is making sure headers are set up - # right -- everything downstream just looks at the headers. There are no - # side channels. - def _clean_up_response_headers_for_sending(self, response: Response) -> Response: - assert type(response) is Response - - headers = response.headers - need_close = False - - # HEAD requests need some special handling: they always act like they - # have Content-Length: 0, and that's how _body_framing treats - # them. But their headers are supposed to match what we would send if - # the request was a GET. (Technically there is one deviation allowed: - # we're allowed to leave out the framing headers -- see - # https://tools.ietf.org/html/rfc7231#section-4.3.2 . But it's just as - # easy to get them right.) - method_for_choosing_headers = cast(bytes, self._request_method) - if method_for_choosing_headers == b"HEAD": - method_for_choosing_headers = b"GET" - framing_type, _ = _body_framing(method_for_choosing_headers, response) - if framing_type in ("chunked", "http/1.0"): - # This response has a body of unknown length. - # If our peer is HTTP/1.1, we use Transfer-Encoding: chunked - # If our peer is HTTP/1.0, we use no framing headers, and close the - # connection afterwards. - # - # Make sure to clear Content-Length (in principle user could have - # set both and then we ignored Content-Length b/c - # Transfer-Encoding overwrote it -- this would be naughty of them, - # but the HTTP spec says that if our peer does this then we have - # to fix it instead of erroring out, so we'll accord the user the - # same respect). - headers = set_comma_header(headers, b"content-length", []) - if self.their_http_version is None or self.their_http_version < b"1.1": - # Either we never got a valid request and are sending back an - # error (their_http_version is None), so we assume the worst; - # or else we did get a valid HTTP/1.0 request, so we know that - # they don't understand chunked encoding. - headers = set_comma_header(headers, b"transfer-encoding", []) - # This is actually redundant ATM, since currently we - # unconditionally disable keep-alive when talking to HTTP/1.0 - # peers. But let's be defensive just in case we add - # Connection: keep-alive support later: - if self._request_method != b"HEAD": - need_close = True - else: - headers = set_comma_header(headers, b"transfer-encoding", [b"chunked"]) - - if not self._cstate.keep_alive or need_close: - # Make sure Connection: close is set - connection = set(get_comma_header(headers, b"connection")) - connection.discard(b"keep-alive") - connection.add(b"close") - headers = set_comma_header(headers, b"connection", sorted(connection)) - - return Response( - headers=headers, - status_code=response.status_code, - http_version=response.http_version, - reason=response.reason, - ) diff --git a/serverenv/lib/python3.9/site-packages/h11/_events.py b/serverenv/lib/python3.9/site-packages/h11/_events.py deleted file mode 100644 index ca1c3ad..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_events.py +++ /dev/null @@ -1,369 +0,0 @@ -# High level events that make up HTTP/1.1 conversations. Loosely inspired by -# the corresponding events in hyper-h2: -# -# http://python-hyper.org/h2/en/stable/api.html#events -# -# Don't subclass these. Stuff will break. - -import re -from abc import ABC -from dataclasses import dataclass -from typing import List, Tuple, Union - -from ._abnf import method, request_target -from ._headers import Headers, normalize_and_validate -from ._util import bytesify, LocalProtocolError, validate - -# Everything in __all__ gets re-exported as part of the h11 public API. -__all__ = [ - "Event", - "Request", - "InformationalResponse", - "Response", - "Data", - "EndOfMessage", - "ConnectionClosed", -] - -method_re = re.compile(method.encode("ascii")) -request_target_re = re.compile(request_target.encode("ascii")) - - -class Event(ABC): - """ - Base class for h11 events. - """ - - __slots__ = () - - -@dataclass(init=False, frozen=True) -class Request(Event): - """The beginning of an HTTP request. - - Fields: - - .. attribute:: method - - An HTTP method, e.g. ``b"GET"`` or ``b"POST"``. Always a byte - string. :term:`Bytes-like objects ` and native - strings containing only ascii characters will be automatically - converted to byte strings. - - .. attribute:: target - - The target of an HTTP request, e.g. ``b"/index.html"``, or one of the - more exotic formats described in `RFC 7320, section 5.3 - `_. Always a byte - string. :term:`Bytes-like objects ` and native - strings containing only ascii characters will be automatically - converted to byte strings. - - .. attribute:: headers - - Request headers, represented as a list of (name, value) pairs. See - :ref:`the header normalization rules ` for details. - - .. attribute:: http_version - - The HTTP protocol version, represented as a byte string like - ``b"1.1"``. See :ref:`the HTTP version normalization rules - ` for details. - - """ - - __slots__ = ("method", "headers", "target", "http_version") - - method: bytes - headers: Headers - target: bytes - http_version: bytes - - def __init__( - self, - *, - method: Union[bytes, str], - headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], - target: Union[bytes, str], - http_version: Union[bytes, str] = b"1.1", - _parsed: bool = False, - ) -> None: - super().__init__() - if isinstance(headers, Headers): - object.__setattr__(self, "headers", headers) - else: - object.__setattr__( - self, "headers", normalize_and_validate(headers, _parsed=_parsed) - ) - if not _parsed: - object.__setattr__(self, "method", bytesify(method)) - object.__setattr__(self, "target", bytesify(target)) - object.__setattr__(self, "http_version", bytesify(http_version)) - else: - object.__setattr__(self, "method", method) - object.__setattr__(self, "target", target) - object.__setattr__(self, "http_version", http_version) - - # "A server MUST respond with a 400 (Bad Request) status code to any - # HTTP/1.1 request message that lacks a Host header field and to any - # request message that contains more than one Host header field or a - # Host header field with an invalid field-value." - # -- https://tools.ietf.org/html/rfc7230#section-5.4 - host_count = 0 - for name, value in self.headers: - if name == b"host": - host_count += 1 - if self.http_version == b"1.1" and host_count == 0: - raise LocalProtocolError("Missing mandatory Host: header") - if host_count > 1: - raise LocalProtocolError("Found multiple Host: headers") - - validate(method_re, self.method, "Illegal method characters") - validate(request_target_re, self.target, "Illegal target characters") - - # This is an unhashable type. - __hash__ = None # type: ignore - - -@dataclass(init=False, frozen=True) -class _ResponseBase(Event): - __slots__ = ("headers", "http_version", "reason", "status_code") - - headers: Headers - http_version: bytes - reason: bytes - status_code: int - - def __init__( - self, - *, - headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], - status_code: int, - http_version: Union[bytes, str] = b"1.1", - reason: Union[bytes, str] = b"", - _parsed: bool = False, - ) -> None: - super().__init__() - if isinstance(headers, Headers): - object.__setattr__(self, "headers", headers) - else: - object.__setattr__( - self, "headers", normalize_and_validate(headers, _parsed=_parsed) - ) - if not _parsed: - object.__setattr__(self, "reason", bytesify(reason)) - object.__setattr__(self, "http_version", bytesify(http_version)) - if not isinstance(status_code, int): - raise LocalProtocolError("status code must be integer") - # Because IntEnum objects are instances of int, but aren't - # duck-compatible (sigh), see gh-72. - object.__setattr__(self, "status_code", int(status_code)) - else: - object.__setattr__(self, "reason", reason) - object.__setattr__(self, "http_version", http_version) - object.__setattr__(self, "status_code", status_code) - - self.__post_init__() - - def __post_init__(self) -> None: - pass - - # This is an unhashable type. - __hash__ = None # type: ignore - - -@dataclass(init=False, frozen=True) -class InformationalResponse(_ResponseBase): - """An HTTP informational response. - - Fields: - - .. attribute:: status_code - - The status code of this response, as an integer. For an - :class:`InformationalResponse`, this is always in the range [100, - 200). - - .. attribute:: headers - - Request headers, represented as a list of (name, value) pairs. See - :ref:`the header normalization rules ` for - details. - - .. attribute:: http_version - - The HTTP protocol version, represented as a byte string like - ``b"1.1"``. See :ref:`the HTTP version normalization rules - ` for details. - - .. attribute:: reason - - The reason phrase of this response, as a byte string. For example: - ``b"OK"``, or ``b"Not Found"``. - - """ - - def __post_init__(self) -> None: - if not (100 <= self.status_code < 200): - raise LocalProtocolError( - "InformationalResponse status_code should be in range " - "[100, 200), not {}".format(self.status_code) - ) - - # This is an unhashable type. - __hash__ = None # type: ignore - - -@dataclass(init=False, frozen=True) -class Response(_ResponseBase): - """The beginning of an HTTP response. - - Fields: - - .. attribute:: status_code - - The status code of this response, as an integer. For an - :class:`Response`, this is always in the range [200, - 1000). - - .. attribute:: headers - - Request headers, represented as a list of (name, value) pairs. See - :ref:`the header normalization rules ` for details. - - .. attribute:: http_version - - The HTTP protocol version, represented as a byte string like - ``b"1.1"``. See :ref:`the HTTP version normalization rules - ` for details. - - .. attribute:: reason - - The reason phrase of this response, as a byte string. For example: - ``b"OK"``, or ``b"Not Found"``. - - """ - - def __post_init__(self) -> None: - if not (200 <= self.status_code < 1000): - raise LocalProtocolError( - "Response status_code should be in range [200, 1000), not {}".format( - self.status_code - ) - ) - - # This is an unhashable type. - __hash__ = None # type: ignore - - -@dataclass(init=False, frozen=True) -class Data(Event): - """Part of an HTTP message body. - - Fields: - - .. attribute:: data - - A :term:`bytes-like object` containing part of a message body. Or, if - using the ``combine=False`` argument to :meth:`Connection.send`, then - any object that your socket writing code knows what to do with, and for - which calling :func:`len` returns the number of bytes that will be - written -- see :ref:`sendfile` for details. - - .. attribute:: chunk_start - - A marker that indicates whether this data object is from the start of a - chunked transfer encoding chunk. This field is ignored when when a Data - event is provided to :meth:`Connection.send`: it is only valid on - events emitted from :meth:`Connection.next_event`. You probably - shouldn't use this attribute at all; see - :ref:`chunk-delimiters-are-bad` for details. - - .. attribute:: chunk_end - - A marker that indicates whether this data object is the last for a - given chunked transfer encoding chunk. This field is ignored when when - a Data event is provided to :meth:`Connection.send`: it is only valid - on events emitted from :meth:`Connection.next_event`. You probably - shouldn't use this attribute at all; see - :ref:`chunk-delimiters-are-bad` for details. - - """ - - __slots__ = ("data", "chunk_start", "chunk_end") - - data: bytes - chunk_start: bool - chunk_end: bool - - def __init__( - self, data: bytes, chunk_start: bool = False, chunk_end: bool = False - ) -> None: - object.__setattr__(self, "data", data) - object.__setattr__(self, "chunk_start", chunk_start) - object.__setattr__(self, "chunk_end", chunk_end) - - # This is an unhashable type. - __hash__ = None # type: ignore - - -# XX FIXME: "A recipient MUST ignore (or consider as an error) any fields that -# are forbidden to be sent in a trailer, since processing them as if they were -# present in the header section might bypass external security filters." -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#chunked.trailer.part -# Unfortunately, the list of forbidden fields is long and vague :-/ -@dataclass(init=False, frozen=True) -class EndOfMessage(Event): - """The end of an HTTP message. - - Fields: - - .. attribute:: headers - - Default value: ``[]`` - - Any trailing headers attached to this message, represented as a list of - (name, value) pairs. See :ref:`the header normalization rules - ` for details. - - Must be empty unless ``Transfer-Encoding: chunked`` is in use. - - """ - - __slots__ = ("headers",) - - headers: Headers - - def __init__( - self, - *, - headers: Union[ - Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]], None - ] = None, - _parsed: bool = False, - ) -> None: - super().__init__() - if headers is None: - headers = Headers([]) - elif not isinstance(headers, Headers): - headers = normalize_and_validate(headers, _parsed=_parsed) - - object.__setattr__(self, "headers", headers) - - # This is an unhashable type. - __hash__ = None # type: ignore - - -@dataclass(frozen=True) -class ConnectionClosed(Event): - """This event indicates that the sender has closed their outgoing - connection. - - Note that this does not necessarily mean that they can't *receive* further - data, because TCP connections are composed to two one-way channels which - can be closed independently. See :ref:`closing` for details. - - No fields. - """ - - pass diff --git a/serverenv/lib/python3.9/site-packages/h11/_headers.py b/serverenv/lib/python3.9/site-packages/h11/_headers.py deleted file mode 100644 index 31da3e2..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_headers.py +++ /dev/null @@ -1,282 +0,0 @@ -import re -from typing import AnyStr, cast, List, overload, Sequence, Tuple, TYPE_CHECKING, Union - -from ._abnf import field_name, field_value -from ._util import bytesify, LocalProtocolError, validate - -if TYPE_CHECKING: - from ._events import Request - -try: - from typing import Literal -except ImportError: - from typing_extensions import Literal # type: ignore - -CONTENT_LENGTH_MAX_DIGITS = 20 # allow up to 1 billion TB - 1 - - -# Facts -# ----- -# -# Headers are: -# keys: case-insensitive ascii -# values: mixture of ascii and raw bytes -# -# "Historically, HTTP has allowed field content with text in the ISO-8859-1 -# charset [ISO-8859-1], supporting other charsets only through use of -# [RFC2047] encoding. In practice, most HTTP header field values use only a -# subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD -# limit their field values to US-ASCII octets. A recipient SHOULD treat other -# octets in field content (obs-text) as opaque data." -# And it deprecates all non-ascii values -# -# Leading/trailing whitespace in header names is forbidden -# -# Values get leading/trailing whitespace stripped -# -# Content-Disposition actually needs to contain unicode semantically; to -# accomplish this it has a terrifically weird way of encoding the filename -# itself as ascii (and even this still has lots of cross-browser -# incompatibilities) -# -# Order is important: -# "a proxy MUST NOT change the order of these field values when forwarding a -# message" -# (and there are several headers where the order indicates a preference) -# -# Multiple occurences of the same header: -# "A sender MUST NOT generate multiple header fields with the same field name -# in a message unless either the entire field value for that header field is -# defined as a comma-separated list [or the header is Set-Cookie which gets a -# special exception]" - RFC 7230. (cookies are in RFC 6265) -# -# So every header aside from Set-Cookie can be merged by b", ".join if it -# occurs repeatedly. But, of course, they can't necessarily be split by -# .split(b","), because quoting. -# -# Given all this mess (case insensitive, duplicates allowed, order is -# important, ...), there doesn't appear to be any standard way to handle -# headers in Python -- they're almost like dicts, but... actually just -# aren't. For now we punt and just use a super simple representation: headers -# are a list of pairs -# -# [(name1, value1), (name2, value2), ...] -# -# where all entries are bytestrings, names are lowercase and have no -# leading/trailing whitespace, and values are bytestrings with no -# leading/trailing whitespace. Searching and updating are done via naive O(n) -# methods. -# -# Maybe a dict-of-lists would be better? - -_content_length_re = re.compile(rb"[0-9]+") -_field_name_re = re.compile(field_name.encode("ascii")) -_field_value_re = re.compile(field_value.encode("ascii")) - - -class Headers(Sequence[Tuple[bytes, bytes]]): - """ - A list-like interface that allows iterating over headers as byte-pairs - of (lowercased-name, value). - - Internally we actually store the representation as three-tuples, - including both the raw original casing, in order to preserve casing - over-the-wire, and the lowercased name, for case-insensitive comparisions. - - r = Request( - method="GET", - target="/", - headers=[("Host", "example.org"), ("Connection", "keep-alive")], - http_version="1.1", - ) - assert r.headers == [ - (b"host", b"example.org"), - (b"connection", b"keep-alive") - ] - assert r.headers.raw_items() == [ - (b"Host", b"example.org"), - (b"Connection", b"keep-alive") - ] - """ - - __slots__ = "_full_items" - - def __init__(self, full_items: List[Tuple[bytes, bytes, bytes]]) -> None: - self._full_items = full_items - - def __bool__(self) -> bool: - return bool(self._full_items) - - def __eq__(self, other: object) -> bool: - return list(self) == list(other) # type: ignore - - def __len__(self) -> int: - return len(self._full_items) - - def __repr__(self) -> str: - return "" % repr(list(self)) - - def __getitem__(self, idx: int) -> Tuple[bytes, bytes]: # type: ignore[override] - _, name, value = self._full_items[idx] - return (name, value) - - def raw_items(self) -> List[Tuple[bytes, bytes]]: - return [(raw_name, value) for raw_name, _, value in self._full_items] - - -HeaderTypes = Union[ - List[Tuple[bytes, bytes]], - List[Tuple[bytes, str]], - List[Tuple[str, bytes]], - List[Tuple[str, str]], -] - - -@overload -def normalize_and_validate(headers: Headers, _parsed: Literal[True]) -> Headers: - ... - - -@overload -def normalize_and_validate(headers: HeaderTypes, _parsed: Literal[False]) -> Headers: - ... - - -@overload -def normalize_and_validate( - headers: Union[Headers, HeaderTypes], _parsed: bool = False -) -> Headers: - ... - - -def normalize_and_validate( - headers: Union[Headers, HeaderTypes], _parsed: bool = False -) -> Headers: - new_headers = [] - seen_content_length = None - saw_transfer_encoding = False - for name, value in headers: - # For headers coming out of the parser, we can safely skip some steps, - # because it always returns bytes and has already run these regexes - # over the data: - if not _parsed: - name = bytesify(name) - value = bytesify(value) - validate(_field_name_re, name, "Illegal header name {!r}", name) - validate(_field_value_re, value, "Illegal header value {!r}", value) - assert isinstance(name, bytes) - assert isinstance(value, bytes) - - raw_name = name - name = name.lower() - if name == b"content-length": - lengths = {length.strip() for length in value.split(b",")} - if len(lengths) != 1: - raise LocalProtocolError("conflicting Content-Length headers") - value = lengths.pop() - validate(_content_length_re, value, "bad Content-Length") - if len(value) > CONTENT_LENGTH_MAX_DIGITS: - raise LocalProtocolError("bad Content-Length") - if seen_content_length is None: - seen_content_length = value - new_headers.append((raw_name, name, value)) - elif seen_content_length != value: - raise LocalProtocolError("conflicting Content-Length headers") - elif name == b"transfer-encoding": - # "A server that receives a request message with a transfer coding - # it does not understand SHOULD respond with 501 (Not - # Implemented)." - # https://tools.ietf.org/html/rfc7230#section-3.3.1 - if saw_transfer_encoding: - raise LocalProtocolError( - "multiple Transfer-Encoding headers", error_status_hint=501 - ) - # "All transfer-coding names are case-insensitive" - # -- https://tools.ietf.org/html/rfc7230#section-4 - value = value.lower() - if value != b"chunked": - raise LocalProtocolError( - "Only Transfer-Encoding: chunked is supported", - error_status_hint=501, - ) - saw_transfer_encoding = True - new_headers.append((raw_name, name, value)) - else: - new_headers.append((raw_name, name, value)) - return Headers(new_headers) - - -def get_comma_header(headers: Headers, name: bytes) -> List[bytes]: - # Should only be used for headers whose value is a list of - # comma-separated, case-insensitive values. - # - # The header name `name` is expected to be lower-case bytes. - # - # Connection: meets these criteria (including cast insensitivity). - # - # Content-Length: technically is just a single value (1*DIGIT), but the - # standard makes reference to implementations that do multiple values, and - # using this doesn't hurt. Ditto, case insensitivity doesn't things either - # way. - # - # Transfer-Encoding: is more complex (allows for quoted strings), so - # splitting on , is actually wrong. For example, this is legal: - # - # Transfer-Encoding: foo; options="1,2", chunked - # - # and should be parsed as - # - # foo; options="1,2" - # chunked - # - # but this naive function will parse it as - # - # foo; options="1 - # 2" - # chunked - # - # However, this is okay because the only thing we are going to do with - # any Transfer-Encoding is reject ones that aren't just "chunked", so - # both of these will be treated the same anyway. - # - # Expect: the only legal value is the literal string - # "100-continue". Splitting on commas is harmless. Case insensitive. - # - out: List[bytes] = [] - for _, found_name, found_raw_value in headers._full_items: - if found_name == name: - found_raw_value = found_raw_value.lower() - for found_split_value in found_raw_value.split(b","): - found_split_value = found_split_value.strip() - if found_split_value: - out.append(found_split_value) - return out - - -def set_comma_header(headers: Headers, name: bytes, new_values: List[bytes]) -> Headers: - # The header name `name` is expected to be lower-case bytes. - # - # Note that when we store the header we use title casing for the header - # names, in order to match the conventional HTTP header style. - # - # Simply calling `.title()` is a blunt approach, but it's correct - # here given the cases where we're using `set_comma_header`... - # - # Connection, Content-Length, Transfer-Encoding. - new_headers: List[Tuple[bytes, bytes]] = [] - for found_raw_name, found_name, found_raw_value in headers._full_items: - if found_name != name: - new_headers.append((found_raw_name, found_raw_value)) - for new_value in new_values: - new_headers.append((name.title(), new_value)) - return normalize_and_validate(new_headers) - - -def has_expect_100_continue(request: "Request") -> bool: - # https://tools.ietf.org/html/rfc7231#section-5.1.1 - # "A server that receives a 100-continue expectation in an HTTP/1.0 request - # MUST ignore that expectation." - if request.http_version < b"1.1": - return False - expect = get_comma_header(request.headers, b"expect") - return b"100-continue" in expect diff --git a/serverenv/lib/python3.9/site-packages/h11/_readers.py b/serverenv/lib/python3.9/site-packages/h11/_readers.py deleted file mode 100644 index 576804c..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_readers.py +++ /dev/null @@ -1,250 +0,0 @@ -# Code to read HTTP data -# -# Strategy: each reader is a callable which takes a ReceiveBuffer object, and -# either: -# 1) consumes some of it and returns an Event -# 2) raises a LocalProtocolError (for consistency -- e.g. we call validate() -# and it might raise a LocalProtocolError, so simpler just to always use -# this) -# 3) returns None, meaning "I need more data" -# -# If they have a .read_eof attribute, then this will be called if an EOF is -# received -- but this is optional. Either way, the actual ConnectionClosed -# event will be generated afterwards. -# -# READERS is a dict describing how to pick a reader. It maps states to either: -# - a reader -# - or, for body readers, a dict of per-framing reader factories - -import re -from typing import Any, Callable, Dict, Iterable, NoReturn, Optional, Tuple, Type, Union - -from ._abnf import chunk_header, header_field, request_line, status_line -from ._events import Data, EndOfMessage, InformationalResponse, Request, Response -from ._receivebuffer import ReceiveBuffer -from ._state import ( - CLIENT, - CLOSED, - DONE, - IDLE, - MUST_CLOSE, - SEND_BODY, - SEND_RESPONSE, - SERVER, -) -from ._util import LocalProtocolError, RemoteProtocolError, Sentinel, validate - -__all__ = ["READERS"] - -header_field_re = re.compile(header_field.encode("ascii")) -obs_fold_re = re.compile(rb"[ \t]+") - - -def _obsolete_line_fold(lines: Iterable[bytes]) -> Iterable[bytes]: - it = iter(lines) - last: Optional[bytes] = None - for line in it: - match = obs_fold_re.match(line) - if match: - if last is None: - raise LocalProtocolError("continuation line at start of headers") - if not isinstance(last, bytearray): - # Cast to a mutable type, avoiding copy on append to ensure O(n) time - last = bytearray(last) - last += b" " - last += line[match.end() :] - else: - if last is not None: - yield last - last = line - if last is not None: - yield last - - -def _decode_header_lines( - lines: Iterable[bytes], -) -> Iterable[Tuple[bytes, bytes]]: - for line in _obsolete_line_fold(lines): - matches = validate(header_field_re, line, "illegal header line: {!r}", line) - yield (matches["field_name"], matches["field_value"]) - - -request_line_re = re.compile(request_line.encode("ascii")) - - -def maybe_read_from_IDLE_client(buf: ReceiveBuffer) -> Optional[Request]: - lines = buf.maybe_extract_lines() - if lines is None: - if buf.is_next_line_obviously_invalid_request_line(): - raise LocalProtocolError("illegal request line") - return None - if not lines: - raise LocalProtocolError("no request line received") - matches = validate( - request_line_re, lines[0], "illegal request line: {!r}", lines[0] - ) - return Request( - headers=list(_decode_header_lines(lines[1:])), _parsed=True, **matches - ) - - -status_line_re = re.compile(status_line.encode("ascii")) - - -def maybe_read_from_SEND_RESPONSE_server( - buf: ReceiveBuffer, -) -> Union[InformationalResponse, Response, None]: - lines = buf.maybe_extract_lines() - if lines is None: - if buf.is_next_line_obviously_invalid_request_line(): - raise LocalProtocolError("illegal request line") - return None - if not lines: - raise LocalProtocolError("no response line received") - matches = validate(status_line_re, lines[0], "illegal status line: {!r}", lines[0]) - http_version = ( - b"1.1" if matches["http_version"] is None else matches["http_version"] - ) - reason = b"" if matches["reason"] is None else matches["reason"] - status_code = int(matches["status_code"]) - class_: Union[Type[InformationalResponse], Type[Response]] = ( - InformationalResponse if status_code < 200 else Response - ) - return class_( - headers=list(_decode_header_lines(lines[1:])), - _parsed=True, - status_code=status_code, - reason=reason, - http_version=http_version, - ) - - -class ContentLengthReader: - def __init__(self, length: int) -> None: - self._length = length - self._remaining = length - - def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]: - if self._remaining == 0: - return EndOfMessage() - data = buf.maybe_extract_at_most(self._remaining) - if data is None: - return None - self._remaining -= len(data) - return Data(data=data) - - def read_eof(self) -> NoReturn: - raise RemoteProtocolError( - "peer closed connection without sending complete message body " - "(received {} bytes, expected {})".format( - self._length - self._remaining, self._length - ) - ) - - -chunk_header_re = re.compile(chunk_header.encode("ascii")) - - -class ChunkedReader: - def __init__(self) -> None: - self._bytes_in_chunk = 0 - # After reading a chunk, we have to throw away the trailing \r\n. - # This tracks the bytes that we need to match and throw away. - self._bytes_to_discard = b"" - self._reading_trailer = False - - def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]: - if self._reading_trailer: - lines = buf.maybe_extract_lines() - if lines is None: - return None - return EndOfMessage(headers=list(_decode_header_lines(lines))) - if self._bytes_to_discard: - data = buf.maybe_extract_at_most(len(self._bytes_to_discard)) - if data is None: - return None - if data != self._bytes_to_discard[: len(data)]: - raise LocalProtocolError( - f"malformed chunk footer: {data!r} (expected {self._bytes_to_discard!r})" - ) - self._bytes_to_discard = self._bytes_to_discard[len(data) :] - if self._bytes_to_discard: - return None - # else, fall through and read some more - assert self._bytes_to_discard == b"" - if self._bytes_in_chunk == 0: - # We need to refill our chunk count - chunk_header = buf.maybe_extract_next_line() - if chunk_header is None: - return None - matches = validate( - chunk_header_re, - chunk_header, - "illegal chunk header: {!r}", - chunk_header, - ) - # XX FIXME: we discard chunk extensions. Does anyone care? - self._bytes_in_chunk = int(matches["chunk_size"], base=16) - if self._bytes_in_chunk == 0: - self._reading_trailer = True - return self(buf) - chunk_start = True - else: - chunk_start = False - assert self._bytes_in_chunk > 0 - data = buf.maybe_extract_at_most(self._bytes_in_chunk) - if data is None: - return None - self._bytes_in_chunk -= len(data) - if self._bytes_in_chunk == 0: - self._bytes_to_discard = b"\r\n" - chunk_end = True - else: - chunk_end = False - return Data(data=data, chunk_start=chunk_start, chunk_end=chunk_end) - - def read_eof(self) -> NoReturn: - raise RemoteProtocolError( - "peer closed connection without sending complete message body " - "(incomplete chunked read)" - ) - - -class Http10Reader: - def __call__(self, buf: ReceiveBuffer) -> Optional[Data]: - data = buf.maybe_extract_at_most(999999999) - if data is None: - return None - return Data(data=data) - - def read_eof(self) -> EndOfMessage: - return EndOfMessage() - - -def expect_nothing(buf: ReceiveBuffer) -> None: - if buf: - raise LocalProtocolError("Got data when expecting EOF") - return None - - -ReadersType = Dict[ - Union[Type[Sentinel], Tuple[Type[Sentinel], Type[Sentinel]]], - Union[Callable[..., Any], Dict[str, Callable[..., Any]]], -] - -READERS: ReadersType = { - (CLIENT, IDLE): maybe_read_from_IDLE_client, - (SERVER, IDLE): maybe_read_from_SEND_RESPONSE_server, - (SERVER, SEND_RESPONSE): maybe_read_from_SEND_RESPONSE_server, - (CLIENT, DONE): expect_nothing, - (CLIENT, MUST_CLOSE): expect_nothing, - (CLIENT, CLOSED): expect_nothing, - (SERVER, DONE): expect_nothing, - (SERVER, MUST_CLOSE): expect_nothing, - (SERVER, CLOSED): expect_nothing, - SEND_BODY: { - "chunked": ChunkedReader, - "content-length": ContentLengthReader, - "http/1.0": Http10Reader, - }, -} diff --git a/serverenv/lib/python3.9/site-packages/h11/_receivebuffer.py b/serverenv/lib/python3.9/site-packages/h11/_receivebuffer.py deleted file mode 100644 index e5c4e08..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_receivebuffer.py +++ /dev/null @@ -1,153 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/h11/_state.py b/serverenv/lib/python3.9/site-packages/h11/_state.py deleted file mode 100644 index 3ad444b..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_state.py +++ /dev/null @@ -1,365 +0,0 @@ -################################################################ -# The core state machine -################################################################ -# -# Rule 1: everything that affects the state machine and state transitions must -# live here in this file. As much as possible goes into the table-based -# representation, but for the bits that don't quite fit, the actual code and -# state must nonetheless live here. -# -# Rule 2: this file does not know about what role we're playing; it only knows -# about HTTP request/response cycles in the abstract. This ensures that we -# don't cheat and apply different rules to local and remote parties. -# -# -# Theory of operation -# =================== -# -# Possibly the simplest way to think about this is that we actually have 5 -# different state machines here. Yes, 5. These are: -# -# 1) The client state, with its complicated automaton (see the docs) -# 2) The server state, with its complicated automaton (see the docs) -# 3) The keep-alive state, with possible states {True, False} -# 4) The SWITCH_CONNECT state, with possible states {False, True} -# 5) The SWITCH_UPGRADE state, with possible states {False, True} -# -# For (3)-(5), the first state listed is the initial state. -# -# (1)-(3) are stored explicitly in member variables. The last -# two are stored implicitly in the pending_switch_proposals set as: -# (state of 4) == (_SWITCH_CONNECT in pending_switch_proposals) -# (state of 5) == (_SWITCH_UPGRADE in pending_switch_proposals) -# -# And each of these machines has two different kinds of transitions: -# -# a) Event-triggered -# b) State-triggered -# -# Event triggered is the obvious thing that you'd think it is: some event -# happens, and if it's the right event at the right time then a transition -# happens. But there are somewhat complicated rules for which machines can -# "see" which events. (As a rule of thumb, if a machine "sees" an event, this -# means two things: the event can affect the machine, and if the machine is -# not in a state where it expects that event then it's an error.) These rules -# are: -# -# 1) The client machine sees all h11.events objects emitted by the client. -# -# 2) The server machine sees all h11.events objects emitted by the server. -# -# It also sees the client's Request event. -# -# And sometimes, server events are annotated with a _SWITCH_* event. For -# example, we can have a (Response, _SWITCH_CONNECT) event, which is -# different from a regular Response event. -# -# 3) The keep-alive machine sees the process_keep_alive_disabled() event -# (which is derived from Request/Response events), and this event -# transitions it from True -> False, or from False -> False. There's no way -# to transition back. -# -# 4&5) The _SWITCH_* machines transition from False->True when we get a -# Request that proposes the relevant type of switch (via -# process_client_switch_proposals), and they go from True->False when we -# get a Response that has no _SWITCH_* annotation. -# -# So that's event-triggered transitions. -# -# State-triggered transitions are less standard. What they do here is couple -# the machines together. The way this works is, when certain *joint* -# configurations of states are achieved, then we automatically transition to a -# new *joint* state. So, for example, if we're ever in a joint state with -# -# client: DONE -# keep-alive: False -# -# then the client state immediately transitions to: -# -# client: MUST_CLOSE -# -# This is fundamentally different from an event-based transition, because it -# doesn't matter how we arrived at the {client: DONE, keep-alive: False} state -# -- maybe the client transitioned SEND_BODY -> DONE, or keep-alive -# transitioned True -> False. Either way, once this precondition is satisfied, -# this transition is immediately triggered. -# -# What if two conflicting state-based transitions get enabled at the same -# time? In practice there's only one case where this arises (client DONE -> -# MIGHT_SWITCH_PROTOCOL versus DONE -> MUST_CLOSE), and we resolve it by -# explicitly prioritizing the DONE -> MIGHT_SWITCH_PROTOCOL transition. -# -# Implementation -# -------------- -# -# The event-triggered transitions for the server and client machines are all -# stored explicitly in a table. Ditto for the state-triggered transitions that -# involve just the server and client state. -# -# The transitions for the other machines, and the state-triggered transitions -# that involve the other machines, are written out as explicit Python code. -# -# It'd be nice if there were some cleaner way to do all this. This isn't -# *too* terrible, but I feel like it could probably be better. -# -# WARNING -# ------- -# -# The script that generates the state machine diagrams for the docs knows how -# to read out the EVENT_TRIGGERED_TRANSITIONS and STATE_TRIGGERED_TRANSITIONS -# tables. But it can't automatically read the transitions that are written -# directly in Python code. So if you touch those, you need to also update the -# script to keep it in sync! -from typing import cast, Dict, Optional, Set, Tuple, Type, Union - -from ._events import * -from ._util import LocalProtocolError, Sentinel - -# Everything in __all__ gets re-exported as part of the h11 public API. -__all__ = [ - "CLIENT", - "SERVER", - "IDLE", - "SEND_RESPONSE", - "SEND_BODY", - "DONE", - "MUST_CLOSE", - "CLOSED", - "MIGHT_SWITCH_PROTOCOL", - "SWITCHED_PROTOCOL", - "ERROR", -] - - -class CLIENT(Sentinel, metaclass=Sentinel): - pass - - -class SERVER(Sentinel, metaclass=Sentinel): - pass - - -# States -class IDLE(Sentinel, metaclass=Sentinel): - pass - - -class SEND_RESPONSE(Sentinel, metaclass=Sentinel): - pass - - -class SEND_BODY(Sentinel, metaclass=Sentinel): - pass - - -class DONE(Sentinel, metaclass=Sentinel): - pass - - -class MUST_CLOSE(Sentinel, metaclass=Sentinel): - pass - - -class CLOSED(Sentinel, metaclass=Sentinel): - pass - - -class ERROR(Sentinel, metaclass=Sentinel): - pass - - -# Switch types -class MIGHT_SWITCH_PROTOCOL(Sentinel, metaclass=Sentinel): - pass - - -class SWITCHED_PROTOCOL(Sentinel, metaclass=Sentinel): - pass - - -class _SWITCH_UPGRADE(Sentinel, metaclass=Sentinel): - pass - - -class _SWITCH_CONNECT(Sentinel, metaclass=Sentinel): - pass - - -EventTransitionType = Dict[ - Type[Sentinel], - Dict[ - Type[Sentinel], - Dict[Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]], Type[Sentinel]], - ], -] - -EVENT_TRIGGERED_TRANSITIONS: EventTransitionType = { - CLIENT: { - IDLE: {Request: SEND_BODY, ConnectionClosed: CLOSED}, - SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, - DONE: {ConnectionClosed: CLOSED}, - MUST_CLOSE: {ConnectionClosed: CLOSED}, - CLOSED: {ConnectionClosed: CLOSED}, - MIGHT_SWITCH_PROTOCOL: {}, - SWITCHED_PROTOCOL: {}, - ERROR: {}, - }, - SERVER: { - IDLE: { - ConnectionClosed: CLOSED, - Response: SEND_BODY, - # Special case: server sees client Request events, in this form - (Request, CLIENT): SEND_RESPONSE, - }, - SEND_RESPONSE: { - InformationalResponse: SEND_RESPONSE, - Response: SEND_BODY, - (InformationalResponse, _SWITCH_UPGRADE): SWITCHED_PROTOCOL, - (Response, _SWITCH_CONNECT): SWITCHED_PROTOCOL, - }, - SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, - DONE: {ConnectionClosed: CLOSED}, - MUST_CLOSE: {ConnectionClosed: CLOSED}, - CLOSED: {ConnectionClosed: CLOSED}, - SWITCHED_PROTOCOL: {}, - ERROR: {}, - }, -} - -StateTransitionType = Dict[ - Tuple[Type[Sentinel], Type[Sentinel]], Dict[Type[Sentinel], Type[Sentinel]] -] - -# NB: there are also some special-case state-triggered transitions hard-coded -# into _fire_state_triggered_transitions below. -STATE_TRIGGERED_TRANSITIONS: StateTransitionType = { - # (Client state, Server state) -> new states - # Protocol negotiation - (MIGHT_SWITCH_PROTOCOL, SWITCHED_PROTOCOL): {CLIENT: SWITCHED_PROTOCOL}, - # Socket shutdown - (CLOSED, DONE): {SERVER: MUST_CLOSE}, - (CLOSED, IDLE): {SERVER: MUST_CLOSE}, - (ERROR, DONE): {SERVER: MUST_CLOSE}, - (DONE, CLOSED): {CLIENT: MUST_CLOSE}, - (IDLE, CLOSED): {CLIENT: MUST_CLOSE}, - (DONE, ERROR): {CLIENT: MUST_CLOSE}, -} - - -class ConnectionState: - def __init__(self) -> None: - # Extra bits of state that don't quite fit into the state model. - - # If this is False then it enables the automatic DONE -> MUST_CLOSE - # transition. Don't set this directly; call .keep_alive_disabled() - self.keep_alive = True - - # This is a subset of {UPGRADE, CONNECT}, containing the proposals - # made by the client for switching protocols. - self.pending_switch_proposals: Set[Type[Sentinel]] = set() - - self.states: Dict[Type[Sentinel], Type[Sentinel]] = {CLIENT: IDLE, SERVER: IDLE} - - def process_error(self, role: Type[Sentinel]) -> None: - self.states[role] = ERROR - self._fire_state_triggered_transitions() - - def process_keep_alive_disabled(self) -> None: - self.keep_alive = False - self._fire_state_triggered_transitions() - - def process_client_switch_proposal(self, switch_event: Type[Sentinel]) -> None: - self.pending_switch_proposals.add(switch_event) - self._fire_state_triggered_transitions() - - def process_event( - self, - role: Type[Sentinel], - event_type: Type[Event], - server_switch_event: Optional[Type[Sentinel]] = None, - ) -> None: - _event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]] = event_type - if server_switch_event is not None: - assert role is SERVER - if server_switch_event not in self.pending_switch_proposals: - raise LocalProtocolError( - "Received server _SWITCH_UPGRADE event without a pending proposal" - ) - _event_type = (event_type, server_switch_event) - if server_switch_event is None and _event_type is Response: - self.pending_switch_proposals = set() - self._fire_event_triggered_transitions(role, _event_type) - # Special case: the server state does get to see Request - # events. - if _event_type is Request: - assert role is CLIENT - self._fire_event_triggered_transitions(SERVER, (Request, CLIENT)) - self._fire_state_triggered_transitions() - - def _fire_event_triggered_transitions( - self, - role: Type[Sentinel], - event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]], - ) -> None: - state = self.states[role] - try: - new_state = EVENT_TRIGGERED_TRANSITIONS[role][state][event_type] - except KeyError: - event_type = cast(Type[Event], event_type) - raise LocalProtocolError( - "can't handle event type {} when role={} and state={}".format( - event_type.__name__, role, self.states[role] - ) - ) from None - self.states[role] = new_state - - def _fire_state_triggered_transitions(self) -> None: - # We apply these rules repeatedly until converging on a fixed point - while True: - start_states = dict(self.states) - - # It could happen that both these special-case transitions are - # enabled at the same time: - # - # DONE -> MIGHT_SWITCH_PROTOCOL - # DONE -> MUST_CLOSE - # - # For example, this will always be true of a HTTP/1.0 client - # requesting CONNECT. If this happens, the protocol switch takes - # priority. From there the client will either go to - # SWITCHED_PROTOCOL, in which case it's none of our business when - # they close the connection, or else the server will deny the - # request, in which case the client will go back to DONE and then - # from there to MUST_CLOSE. - if self.pending_switch_proposals: - if self.states[CLIENT] is DONE: - self.states[CLIENT] = MIGHT_SWITCH_PROTOCOL - - if not self.pending_switch_proposals: - if self.states[CLIENT] is MIGHT_SWITCH_PROTOCOL: - self.states[CLIENT] = DONE - - if not self.keep_alive: - for role in (CLIENT, SERVER): - if self.states[role] is DONE: - self.states[role] = MUST_CLOSE - - # Tabular state-triggered transitions - joint_state = (self.states[CLIENT], self.states[SERVER]) - changes = STATE_TRIGGERED_TRANSITIONS.get(joint_state, {}) - self.states.update(changes) - - if self.states == start_states: - # Fixed point reached - return - - def start_next_cycle(self) -> None: - if self.states != {CLIENT: DONE, SERVER: DONE}: - raise LocalProtocolError( - f"not in a reusable state. self.states={self.states}" - ) - # Can't reach DONE/DONE with any of these active, but still, let's be - # sure. - assert self.keep_alive - assert not self.pending_switch_proposals - self.states = {CLIENT: IDLE, SERVER: IDLE} diff --git a/serverenv/lib/python3.9/site-packages/h11/_util.py b/serverenv/lib/python3.9/site-packages/h11/_util.py deleted file mode 100644 index 6718445..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_util.py +++ /dev/null @@ -1,135 +0,0 @@ -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/serverenv/lib/python3.9/site-packages/h11/_version.py b/serverenv/lib/python3.9/site-packages/h11/_version.py deleted file mode 100644 index 76e7327..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_version.py +++ /dev/null @@ -1,16 +0,0 @@ -# This file must be kept very simple, because it is consumed from several -# places -- it is imported by h11/__init__.py, execfile'd by setup.py, etc. - -# We use a simple scheme: -# 1.0.0 -> 1.0.0+dev -> 1.1.0 -> 1.1.0+dev -# where the +dev versions are never released into the wild, they're just what -# we stick into the VCS in between releases. -# -# This is compatible with PEP 440: -# http://legacy.python.org/dev/peps/pep-0440/ -# via the use of the "local suffix" "+dev", which is disallowed on index -# servers and causes 1.0.0+dev to sort after plain 1.0.0, which is what we -# want. (Contrast with the special suffix 1.0.0.dev, which sorts *before* -# 1.0.0.) - -__version__ = "0.16.0" diff --git a/serverenv/lib/python3.9/site-packages/h11/_writers.py b/serverenv/lib/python3.9/site-packages/h11/_writers.py deleted file mode 100644 index 939cdb9..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/_writers.py +++ /dev/null @@ -1,145 +0,0 @@ -# Code to read HTTP data -# -# Strategy: each writer takes an event + a write-some-bytes function, which is -# calls. -# -# WRITERS is a dict describing how to pick a reader. It maps states to either: -# - a writer -# - or, for body writers, a dict of framin-dependent writer factories - -from typing import Any, Callable, Dict, List, Tuple, Type, Union - -from ._events import Data, EndOfMessage, Event, InformationalResponse, Request, Response -from ._headers import Headers -from ._state import CLIENT, IDLE, SEND_BODY, SEND_RESPONSE, SERVER -from ._util import LocalProtocolError, Sentinel - -__all__ = ["WRITERS"] - -Writer = Callable[[bytes], Any] - - -def write_headers(headers: Headers, write: Writer) -> None: - # "Since the Host field-value is critical information for handling a - # request, a user agent SHOULD generate Host as the first header field - # following the request-line." - RFC 7230 - raw_items = headers._full_items - for raw_name, name, value in raw_items: - if name == b"host": - write(b"%s: %s\r\n" % (raw_name, value)) - for raw_name, name, value in raw_items: - if name != b"host": - write(b"%s: %s\r\n" % (raw_name, value)) - write(b"\r\n") - - -def write_request(request: Request, write: Writer) -> None: - if request.http_version != b"1.1": - raise LocalProtocolError("I only send HTTP/1.1") - write(b"%s %s HTTP/1.1\r\n" % (request.method, request.target)) - write_headers(request.headers, write) - - -# Shared between InformationalResponse and Response -def write_any_response( - response: Union[InformationalResponse, Response], write: Writer -) -> None: - if response.http_version != b"1.1": - raise LocalProtocolError("I only send HTTP/1.1") - status_bytes = str(response.status_code).encode("ascii") - # We don't bother sending ascii status messages like "OK"; they're - # optional and ignored by the protocol. (But the space after the numeric - # status code is mandatory.) - # - # XX FIXME: could at least make an effort to pull out the status message - # from stdlib's http.HTTPStatus table. Or maybe just steal their enums - # (either by import or copy/paste). We already accept them as status codes - # since they're of type IntEnum < int. - write(b"HTTP/1.1 %s %s\r\n" % (status_bytes, response.reason)) - write_headers(response.headers, write) - - -class BodyWriter: - def __call__(self, event: Event, write: Writer) -> None: - if type(event) is Data: - self.send_data(event.data, write) - elif type(event) is EndOfMessage: - self.send_eom(event.headers, write) - else: # pragma: no cover - assert False - - def send_data(self, data: bytes, write: Writer) -> None: - pass - - def send_eom(self, headers: Headers, write: Writer) -> None: - pass - - -# -# These are all careful not to do anything to 'data' except call len(data) and -# write(data). This allows us to transparently pass-through funny objects, -# like placeholder objects referring to files on disk that will be sent via -# sendfile(2). -# -class ContentLengthWriter(BodyWriter): - def __init__(self, length: int) -> None: - self._length = length - - def send_data(self, data: bytes, write: Writer) -> None: - self._length -= len(data) - if self._length < 0: - raise LocalProtocolError("Too much data for declared Content-Length") - write(data) - - def send_eom(self, headers: Headers, write: Writer) -> None: - if self._length != 0: - raise LocalProtocolError("Too little data for declared Content-Length") - if headers: - raise LocalProtocolError("Content-Length and trailers don't mix") - - -class ChunkedWriter(BodyWriter): - def send_data(self, data: bytes, write: Writer) -> None: - # if we encoded 0-length data in the naive way, it would look like an - # end-of-message. - if not data: - return - write(b"%x\r\n" % len(data)) - write(data) - write(b"\r\n") - - def send_eom(self, headers: Headers, write: Writer) -> None: - write(b"0\r\n") - write_headers(headers, write) - - -class Http10Writer(BodyWriter): - def send_data(self, data: bytes, write: Writer) -> None: - write(data) - - def send_eom(self, headers: Headers, write: Writer) -> None: - if headers: - raise LocalProtocolError("can't send trailers to HTTP/1.0 client") - # no need to close the socket ourselves, that will be taken care of by - # Connection: close machinery - - -WritersType = Dict[ - Union[Tuple[Type[Sentinel], Type[Sentinel]], Type[Sentinel]], - Union[ - Dict[str, Type[BodyWriter]], - Callable[[Union[InformationalResponse, Response], Writer], None], - Callable[[Request, Writer], None], - ], -] - -WRITERS: WritersType = { - (CLIENT, IDLE): write_request, - (SERVER, IDLE): write_any_response, - (SERVER, SEND_RESPONSE): write_any_response, - SEND_BODY: { - "chunked": ChunkedWriter, - "content-length": ContentLengthWriter, - "http/1.0": Http10Writer, - }, -} diff --git a/serverenv/lib/python3.9/site-packages/h11/py.typed b/serverenv/lib/python3.9/site-packages/h11/py.typed deleted file mode 100644 index f5642f7..0000000 --- a/serverenv/lib/python3.9/site-packages/h11/py.typed +++ /dev/null @@ -1 +0,0 @@ -Marker diff --git a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/LICENSE b/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/LICENSE deleted file mode 100644 index db41662..0000000 --- a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015-2020 Cory Benfield and 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/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/METADATA deleted file mode 100644 index 227b270..0000000 --- a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/METADATA +++ /dev/null @@ -1,128 +0,0 @@ -Metadata-Version: 2.2 -Name: h2 -Version: 4.2.0 -Summary: Pure-Python HTTP/2 protocol implementation -Author-email: Cory Benfield -Maintainer-email: Thomas Kriechbaumer -License: The MIT License (MIT) - - Copyright (c) 2015-2020 Cory Benfield and 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. - -Project-URL: Homepage, https://github.com/python-hyper/h2/ -Project-URL: Bug Reports, https://github.com/python-hyper/h2/issues -Project-URL: Source, https://github.com/python-hyper/h2/ -Project-URL: Documentation, https://python-hyper.org/ -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.9 -Description-Content-Type: text/x-rst -License-File: LICENSE -Requires-Dist: hyperframe<7,>=6.1 -Requires-Dist: hpack<5,>=4.1 - -========================= -h2: HTTP/2 Protocol Stack -========================= - -.. image:: https://github.com/python-hyper/h2/workflows/CI/badge.svg - :target: https://github.com/python-hyper/h2/actions - :alt: Build Status -.. image:: https://codecov.io/gh/python-hyper/h2/branch/master/graph/badge.svg - :target: https://codecov.io/gh/python-hyper/h2 - :alt: Code Coverage -.. image:: https://readthedocs.org/projects/h2/badge/?version=latest - :target: https://h2.readthedocs.io/en/latest/ - :alt: Documentation Status -.. image:: https://img.shields.io/badge/chat-join_now-brightgreen.svg - :target: https://gitter.im/python-hyper/community - :alt: Chat community - -.. image:: https://raw.github.com/python-hyper/documentation/master/source/logo/hyper-black-bg-white.png - -This repository contains a pure-Python implementation of a HTTP/2 protocol -stack. It's written from the ground up to be embeddable in whatever program you -choose to use, ensuring that you can speak HTTP/2 regardless of your -programming paradigm. - -You use it like this: - -.. code-block:: python - - import h2.connection - import h2.config - - config = h2.config.H2Configuration() - conn = h2.connection.H2Connection(config=config) - conn.send_headers(stream_id=stream_id, headers=headers) - conn.send_data(stream_id, data) - socket.sendall(conn.data_to_send()) - events = conn.receive_data(socket_data) - -This repository does not provide a parsing layer, a network layer, or any rules -about concurrency. Instead, it's a purely in-memory solution, defined in terms -of data actions and HTTP/2 frames. This is one building block of a full Python -HTTP implementation. - -To install it, just run: - -.. code-block:: console - - $ python -m pip install h2 - -Documentation -============= - -Documentation is available at https://h2.readthedocs.io . - -Contributing -============ - -``h2`` welcomes contributions from anyone! Unlike many other projects we -are happy to accept cosmetic contributions and small contributions, in addition -to large feature requests and changes. - -Before you contribute (either by opening an issue or filing a pull request), -please `read the contribution guidelines`_. - -.. _read the contribution guidelines: http://python-hyper.org/en/latest/contributing.html - -License -======= - -``h2`` is made available under the MIT License. For more details, see the -``LICENSE`` file in the repository. - -Authors -======= - -``h2`` was authored by Cory Benfield and is maintained -by the members of `python-hyper `_. diff --git a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/RECORD deleted file mode 100644 index 340818c..0000000 --- a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/RECORD +++ /dev/null @@ -1,29 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/config.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/connection.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/errors.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/events.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/exceptions.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/frame_buffer.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/settings.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/stream.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/utilities.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/h2/windows.cpython-39.pyc,, -h2-4.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -h2-4.2.0.dist-info/LICENSE,sha256=emWlrwy6vxwWJRx8ayt8tG0WpyIueZdbm2H81mouPyg,1102 -h2-4.2.0.dist-info/METADATA,sha256=pZL7uo7jiewzRUfyJFXfMgi9ZiCJHvOtn6V_kkGADYE,5116 -h2-4.2.0.dist-info/RECORD,, -h2-4.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91 -h2-4.2.0.dist-info/top_level.txt,sha256=Hiulx8KxI2jFUM1dG7-CZeRkO3j50MBwCLG36Vrq-kI,3 -h2/__init__.py,sha256=HNxW_2c-oB4u2NGUs5FYKUwnpqR9zLDKWxktmvVaTzs,109 -h2/config.py,sha256=Z-wr5rFizcB2-WTVWCuGte8y-8ceb5B2-rlcV0L5tuU,8344 -h2/connection.py,sha256=aGyZqm_vhxoTaLZOg0cW-YlXhHy8q1zzh2qlIBhK0gk,86816 -h2/errors.py,sha256=S-TdYaJfP_hwlFj2uQGJGQ4S4_yWiU_9E44aPxdACbE,1581 -h2/events.py,sha256=sJvo9KEpJ01cggx2tk0z2FIEgdxJ32NDCouwGtJM2-I,22764 -h2/exceptions.py,sha256=3Em3mLMQBHxYpOKoaPdKCGFGn8A9re9ABtUdKlY3bZM,5308 -h2/frame_buffer.py,sha256=0aOjqxygfGMUkPVroSOlcaYyWMC8bceZjbRP6a2QP_g,6537 -h2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -h2/settings.py,sha256=jRBkghniIiUGQv162Q3mzWQTmi0F45UmmzIHjb4Mu1U,12323 -h2/stream.py,sha256=dOPUcvaO8htmY5c-Bsy-yDqD0puo6NZy_-RR2W4cZ08,57963 -h2/utilities.py,sha256=gwfwlqR_zo0C_EIBsJVETJvotP8sspHeTPTD4f8i_Ls,25988 -h2/windows.py,sha256=JpWNhDv-x4J5jIXSWp0INHkq9IIgPP27xr9FXYvazFE,5492 diff --git a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/WHEEL deleted file mode 100644 index 505164b..0000000 --- a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (75.8.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/top_level.txt b/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/top_level.txt deleted file mode 100644 index c48b563..0000000 --- a/serverenv/lib/python3.9/site-packages/h2-4.2.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -h2 diff --git a/serverenv/lib/python3.9/site-packages/h2/__init__.py b/serverenv/lib/python3.9/site-packages/h2/__init__.py deleted file mode 100644 index 0764daa..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -""" -HTTP/2 protocol implementation for Python. -""" -from __future__ import annotations - -__version__ = "4.2.0" diff --git a/serverenv/lib/python3.9/site-packages/h2/config.py b/serverenv/lib/python3.9/site-packages/h2/config.py deleted file mode 100644 index cbc3b1e..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/config.py +++ /dev/null @@ -1,212 +0,0 @@ -""" -h2/config -~~~~~~~~~ - -Objects for controlling the configuration of the HTTP/2 stack. -""" -from __future__ import annotations - -import sys -from typing import Any - - -class _BooleanConfigOption: - """ - Descriptor for handling a boolean config option. This will block - attempts to set boolean config options to non-bools. - """ - - def __init__(self, name: str) -> None: - self.name = name - self.attr_name = f"_{self.name}" - - def __get__(self, instance: Any, owner: Any) -> bool: - return getattr(instance, self.attr_name) # type: ignore - - def __set__(self, instance: Any, value: bool) -> None: - if not isinstance(value, bool): - msg = f"{self.name} must be a bool" - raise ValueError(msg) # noqa: TRY004 - setattr(instance, self.attr_name, value) - - -class DummyLogger: - """ - A Logger object that does not actual logging, hence a DummyLogger. - - For the class the log operation is merely a no-op. The intent is to avoid - conditionals being sprinkled throughout the h2 code for calls to - logging functions when no logger is passed into the corresponding object. - """ - - def __init__(self, *vargs) -> None: # type: ignore - pass - - def debug(self, *vargs, **kwargs) -> None: # type: ignore - """ - No-op logging. Only level needed for now. - """ - - def trace(self, *vargs, **kwargs) -> None: # type: ignore - """ - No-op logging. Only level needed for now. - """ - - -class OutputLogger: - """ - A Logger object that prints to stderr or any other file-like object. - - This class is provided for convenience and not part of the stable API. - - :param file: A file-like object passed to the print function. - Defaults to ``sys.stderr``. - :param trace: Enables trace-level output. Defaults to ``False``. - """ - - def __init__(self, file=None, trace_level=False) -> None: # type: ignore - super().__init__() - self.file = file or sys.stderr - self.trace_level = trace_level - - def debug(self, fmtstr, *args) -> None: # type: ignore - print(f"h2 (debug): {fmtstr % args}", file=self.file) - - def trace(self, fmtstr, *args) -> None: # type: ignore - if self.trace_level: - print(f"h2 (trace): {fmtstr % args}", file=self.file) - - -class H2Configuration: - """ - An object that controls the way a single HTTP/2 connection behaves. - - This object allows the users to customize behaviour. In particular, it - allows users to enable or disable optional features, or to otherwise handle - various unusual behaviours. - - This object has very little behaviour of its own: it mostly just ensures - that configuration is self-consistent. - - :param client_side: Whether this object is to be used on the client side of - a connection, or on the server side. Affects the logic used by the - state machine, the default settings values, the allowable stream IDs, - and several other properties. Defaults to ``True``. - :type client_side: ``bool`` - - :param header_encoding: Controls whether the headers emitted by this object - in events are transparently decoded to ``unicode`` strings, and what - encoding is used to do that decoding. This defaults to ``None``, - meaning that headers will be returned as bytes. To automatically - decode headers (that is, to return them as unicode strings), this can - be set to the string name of any encoding, e.g. ``'utf-8'``. - - .. versionchanged:: 3.0.0 - Changed default value from ``'utf-8'`` to ``None`` - - :type header_encoding: ``str``, ``False``, or ``None`` - - :param validate_outbound_headers: Controls whether the headers emitted - by this object are validated against the rules in RFC 7540. - Disabling this setting will cause outbound header validation to - be skipped, and allow the object to emit headers that may be illegal - according to RFC 7540. Defaults to ``True``. - :type validate_outbound_headers: ``bool`` - - :param normalize_outbound_headers: Controls whether the headers emitted - by this object are normalized before sending. Disabling this setting - will cause outbound header normalization to be skipped, and allow - the object to emit headers that may be illegal according to - RFC 7540. Defaults to ``True``. - :type normalize_outbound_headers: ``bool`` - - :param split_outbound_cookies: Controls whether the outbound cookie - headers are split before sending or not. According to RFC 7540 - - 8.1.2.5 the outbound header cookie headers may be split to improve - headers compression. Default is ``False``. - :type split_outbound_cookies: ``bool`` - - :param validate_inbound_headers: Controls whether the headers received - by this object are validated against the rules in RFC 7540. - Disabling this setting will cause inbound header validation to - be skipped, and allow the object to receive headers that may be illegal - according to RFC 7540. Defaults to ``True``. - :type validate_inbound_headers: ``bool`` - - :param normalize_inbound_headers: Controls whether the headers received by - this object are normalized according to the rules of RFC 7540. - Disabling this setting may lead to h2 emitting header blocks that - some RFCs forbid, e.g. with multiple cookie fields. - - .. versionadded:: 3.0.0 - - :type normalize_inbound_headers: ``bool`` - - :param logger: A logger that conforms to the requirements for this module, - those being no I/O and no context switches, which is needed in order - to run in asynchronous operation. - - .. versionadded:: 2.6.0 - - :type logger: ``logging.Logger`` - """ - - client_side = _BooleanConfigOption("client_side") - validate_outbound_headers = _BooleanConfigOption( - "validate_outbound_headers", - ) - normalize_outbound_headers = _BooleanConfigOption( - "normalize_outbound_headers", - ) - split_outbound_cookies = _BooleanConfigOption( - "split_outbound_cookies", - ) - validate_inbound_headers = _BooleanConfigOption( - "validate_inbound_headers", - ) - normalize_inbound_headers = _BooleanConfigOption( - "normalize_inbound_headers", - ) - - def __init__(self, - client_side: bool = True, - header_encoding: bool | str | None = None, - validate_outbound_headers: bool = True, - normalize_outbound_headers: bool = True, - split_outbound_cookies: bool = False, - validate_inbound_headers: bool = True, - normalize_inbound_headers: bool = True, - logger: DummyLogger | OutputLogger | None = None) -> None: - self.client_side = client_side - self.header_encoding = header_encoding - self.validate_outbound_headers = validate_outbound_headers - self.normalize_outbound_headers = normalize_outbound_headers - self.split_outbound_cookies = split_outbound_cookies - self.validate_inbound_headers = validate_inbound_headers - self.normalize_inbound_headers = normalize_inbound_headers - self.logger = logger or DummyLogger(__name__) - - @property - def header_encoding(self) -> bool | str | None: - """ - Controls whether the headers emitted by this object in events are - transparently decoded to ``unicode`` strings, and what encoding is used - to do that decoding. This defaults to ``None``, meaning that headers - will be returned as bytes. To automatically decode headers (that is, to - return them as unicode strings), this can be set to the string name of - any encoding, e.g. ``'utf-8'``. - """ - return self._header_encoding - - @header_encoding.setter - def header_encoding(self, value: bool | str | None) -> None: - """ - Enforces constraints on the value of header encoding. - """ - if not isinstance(value, (bool, str, type(None))): - msg = "header_encoding must be bool, string, or None" - raise ValueError(msg) # noqa: TRY004 - if value is True: - msg = "header_encoding cannot be True" - raise ValueError(msg) - self._header_encoding = value diff --git a/serverenv/lib/python3.9/site-packages/h2/connection.py b/serverenv/lib/python3.9/site-packages/h2/connection.py deleted file mode 100644 index 28be9fc..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/connection.py +++ /dev/null @@ -1,2112 +0,0 @@ -""" -h2/connection -~~~~~~~~~~~~~ - -An implementation of a HTTP/2 connection. -""" -from __future__ import annotations - -import base64 -from enum import Enum, IntEnum -from typing import TYPE_CHECKING, Any, Callable - -from hpack.exceptions import HPACKError, OversizedHeaderListError -from hpack.hpack import Decoder, Encoder -from hyperframe.exceptions import InvalidPaddingError -from hyperframe.frame import ( - AltSvcFrame, - ContinuationFrame, - DataFrame, - ExtensionFrame, - Frame, - GoAwayFrame, - HeadersFrame, - PingFrame, - PriorityFrame, - PushPromiseFrame, - RstStreamFrame, - SettingsFrame, - WindowUpdateFrame, -) - -from .config import H2Configuration -from .errors import ErrorCodes, _error_code_from_int -from .events import ( - AlternativeServiceAvailable, - ConnectionTerminated, - Event, - InformationalResponseReceived, - PingAckReceived, - PingReceived, - PriorityUpdated, - RemoteSettingsChanged, - RequestReceived, - ResponseReceived, - SettingsAcknowledged, - TrailersReceived, - UnknownFrameReceived, - WindowUpdated, -) -from .exceptions import ( - DenialOfServiceError, - FlowControlError, - FrameTooLargeError, - NoAvailableStreamIDError, - NoSuchStreamError, - ProtocolError, - RFC1122Error, - StreamClosedError, - StreamIDTooLowError, - TooManyStreamsError, -) -from .frame_buffer import FrameBuffer -from .settings import ChangedSetting, SettingCodes, Settings -from .stream import H2Stream, StreamClosedBy -from .utilities import SizeLimitDict, guard_increment_window -from .windows import WindowManager - -if TYPE_CHECKING: # pragma: no cover - from collections.abc import Iterable - - from hpack.struct import Header, HeaderWeaklyTyped - - -class ConnectionState(Enum): - IDLE = 0 - CLIENT_OPEN = 1 - SERVER_OPEN = 2 - CLOSED = 3 - - -class ConnectionInputs(Enum): - SEND_HEADERS = 0 - SEND_PUSH_PROMISE = 1 - SEND_DATA = 2 - SEND_GOAWAY = 3 - SEND_WINDOW_UPDATE = 4 - SEND_PING = 5 - SEND_SETTINGS = 6 - SEND_RST_STREAM = 7 - SEND_PRIORITY = 8 - RECV_HEADERS = 9 - RECV_PUSH_PROMISE = 10 - RECV_DATA = 11 - RECV_GOAWAY = 12 - RECV_WINDOW_UPDATE = 13 - RECV_PING = 14 - RECV_SETTINGS = 15 - RECV_RST_STREAM = 16 - RECV_PRIORITY = 17 - SEND_ALTERNATIVE_SERVICE = 18 # Added in 2.3.0 - RECV_ALTERNATIVE_SERVICE = 19 # Added in 2.3.0 - - -class AllowedStreamIDs(IntEnum): - EVEN = 0 - ODD = 1 - - -class H2ConnectionStateMachine: - """ - A single HTTP/2 connection state machine. - - This state machine, while defined in its own class, is logically part of - the H2Connection class also defined in this file. The state machine itself - maintains very little state directly, instead focusing entirely on managing - state transitions. - """ - - # For the purposes of this state machine we treat HEADERS and their - # associated CONTINUATION frames as a single jumbo frame. The protocol - # allows/requires this by preventing other frames from being interleved in - # between HEADERS/CONTINUATION frames. - # - # The _transitions dictionary contains a mapping of tuples of - # (state, input) to tuples of (side_effect_function, end_state). This map - # contains all allowed transitions: anything not in this map is invalid - # and immediately causes a transition to ``closed``. - - _transitions = { - # State: idle - (ConnectionState.IDLE, ConnectionInputs.SEND_HEADERS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.IDLE, ConnectionInputs.RECV_HEADERS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.IDLE, ConnectionInputs.SEND_SETTINGS): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_SETTINGS): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_WINDOW_UPDATE): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_WINDOW_UPDATE): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_PING): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_PING): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.IDLE, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.IDLE, ConnectionInputs.SEND_PRIORITY): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_PRIORITY): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_ALTERNATIVE_SERVICE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.IDLE, ConnectionInputs.RECV_ALTERNATIVE_SERVICE): - (None, ConnectionState.CLIENT_OPEN), - - # State: open, client side. - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_HEADERS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_DATA): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_WINDOW_UPDATE): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_PING): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_SETTINGS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_PRIORITY): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_HEADERS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_PUSH_PROMISE): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_DATA): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_WINDOW_UPDATE): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_PING): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_SETTINGS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_RST_STREAM): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_RST_STREAM): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_PRIORITY): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, - ConnectionInputs.RECV_ALTERNATIVE_SERVICE): - (None, ConnectionState.CLIENT_OPEN), - - # State: open, server side. - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_HEADERS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_PUSH_PROMISE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_DATA): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_WINDOW_UPDATE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_PING): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_SETTINGS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_PRIORITY): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_HEADERS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_DATA): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_WINDOW_UPDATE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_PING): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_SETTINGS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_PRIORITY): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_RST_STREAM): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_RST_STREAM): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, - ConnectionInputs.SEND_ALTERNATIVE_SERVICE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, - ConnectionInputs.RECV_ALTERNATIVE_SERVICE): - (None, ConnectionState.SERVER_OPEN), - - # State: closed - (ConnectionState.CLOSED, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.CLOSED, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - } - - def __init__(self) -> None: - self.state = ConnectionState.IDLE - - def process_input(self, input_: ConnectionInputs) -> list[Event]: - """ - Process a specific input in the state machine. - """ - if not isinstance(input_, ConnectionInputs): - msg = "Input must be an instance of ConnectionInputs" - raise ValueError(msg) # noqa: TRY004 - - try: - func, target_state = self._transitions[(self.state, input_)] - except KeyError as e: - old_state = self.state - self.state = ConnectionState.CLOSED - msg = f"Invalid input {input_} in state {old_state}" - raise ProtocolError(msg) from e - else: - self.state = target_state - if func is not None: # pragma: no cover - return func() - - return [] - - -class H2Connection: - """ - A low-level HTTP/2 connection object. This handles building and receiving - frames and maintains both connection and per-stream state for all streams - on this connection. - - This wraps a HTTP/2 Connection state machine implementation, ensuring that - frames can only be sent/received when the connection is in a valid state. - It also builds stream state machines on demand to ensure that the - constraints of those state machines are met as well. Attempts to create - frames that cannot be sent will raise a ``ProtocolError``. - - .. versionchanged:: 2.3.0 - Added the ``header_encoding`` keyword argument. - - .. versionchanged:: 2.5.0 - Added the ``config`` keyword argument. Deprecated the ``client_side`` - and ``header_encoding`` parameters. - - .. versionchanged:: 3.0.0 - Removed deprecated parameters and properties. - - :param config: The configuration for the HTTP/2 connection. - - .. versionadded:: 2.5.0 - - :type config: :class:`H2Configuration ` - """ - - # The initial maximum outbound frame size. This can be changed by receiving - # a settings frame. - DEFAULT_MAX_OUTBOUND_FRAME_SIZE = 65535 - - # The initial maximum inbound frame size. This is somewhat arbitrarily - # chosen. - DEFAULT_MAX_INBOUND_FRAME_SIZE = 2**24 - - # The highest acceptable stream ID. - HIGHEST_ALLOWED_STREAM_ID = 2**31 - 1 - - # The largest acceptable window increment. - MAX_WINDOW_INCREMENT = 2**31 - 1 - - # The initial default value of SETTINGS_MAX_HEADER_LIST_SIZE. - DEFAULT_MAX_HEADER_LIST_SIZE = 2**16 - - # Keep in memory limited amount of results for streams closes - MAX_CLOSED_STREAMS = 2**16 - - def __init__(self, config: H2Configuration | None = None) -> None: - self.state_machine = H2ConnectionStateMachine() - self.streams: dict[int, H2Stream] = {} - self.highest_inbound_stream_id = 0 - self.highest_outbound_stream_id = 0 - self.encoder = Encoder() - self.decoder = Decoder() - - # This won't always actually do anything: for versions of HPACK older - # than 2.3.0 it does nothing. However, we have to try! - self.decoder.max_header_list_size = self.DEFAULT_MAX_HEADER_LIST_SIZE - - #: The configuration for this HTTP/2 connection object. - #: - #: .. versionadded:: 2.5.0 - self.config = config or H2Configuration(client_side=True) - - # Objects that store settings, including defaults. - # - # We set the MAX_CONCURRENT_STREAMS value to 100 because its default is - # unbounded, and that's a dangerous default because it allows - # essentially unbounded resources to be allocated regardless of how - # they will be used. 100 should be suitable for the average - # application. This default obviously does not apply to the remote - # peer's settings: the remote peer controls them! - # - # We also set MAX_HEADER_LIST_SIZE to a reasonable value. This is to - # advertise our defence against CVE-2016-6581. However, not all - # versions of HPACK will let us do it. That's ok: we should at least - # suggest that we're not vulnerable. - self.local_settings = Settings( - client=self.config.client_side, - initial_values={ - SettingCodes.MAX_CONCURRENT_STREAMS: 100, - SettingCodes.MAX_HEADER_LIST_SIZE: - self.DEFAULT_MAX_HEADER_LIST_SIZE, - }, - ) - self.remote_settings = Settings(client=not self.config.client_side) - - # The current value of the connection flow control windows on the - # connection. - self.outbound_flow_control_window = ( - self.remote_settings.initial_window_size - ) - - #: The maximum size of a frame that can be emitted by this peer, in - #: bytes. - self.max_outbound_frame_size = self.remote_settings.max_frame_size - - #: The maximum size of a frame that can be received by this peer, in - #: bytes. - self.max_inbound_frame_size = self.local_settings.max_frame_size - - # Buffer for incoming data. - self.incoming_buffer = FrameBuffer(server=not self.config.client_side) - - # A private variable to store a sequence of received header frames - # until completion. - self._header_frames: list[Frame] = [] - - # Data that needs to be sent. - self._data_to_send = bytearray() - - # Keeps track of how streams are closed. - # Used to ensure that we don't blow up in the face of frames that were - # in flight when a RST_STREAM was sent. - # Also used to determine whether we should consider a frame received - # while a stream is closed as either a stream error or a connection - # error. - self._closed_streams: dict[int, StreamClosedBy | None] = SizeLimitDict( - size_limit=self.MAX_CLOSED_STREAMS, - ) - - # The flow control window manager for the connection. - self._inbound_flow_control_window_manager = WindowManager( - max_window_size=self.local_settings.initial_window_size, - ) - - # When in doubt use dict-dispatch. - self._frame_dispatch_table: dict[type[Frame], Callable] = { # type: ignore - HeadersFrame: self._receive_headers_frame, - PushPromiseFrame: self._receive_push_promise_frame, - SettingsFrame: self._receive_settings_frame, - DataFrame: self._receive_data_frame, - WindowUpdateFrame: self._receive_window_update_frame, - PingFrame: self._receive_ping_frame, - RstStreamFrame: self._receive_rst_stream_frame, - PriorityFrame: self._receive_priority_frame, - GoAwayFrame: self._receive_goaway_frame, - ContinuationFrame: self._receive_naked_continuation, - AltSvcFrame: self._receive_alt_svc_frame, - ExtensionFrame: self._receive_unknown_frame, - } - - def _prepare_for_sending(self, frames: list[Frame]) -> None: - if not frames: - return - self._data_to_send += b"".join(f.serialize() for f in frames) - assert all(f.body_len <= self.max_outbound_frame_size for f in frames) - - def _open_streams(self, remainder: int) -> int: - """ - A common method of counting number of open streams. Returns the number - of streams that are open *and* that have (stream ID % 2) == remainder. - While it iterates, also deletes any closed streams. - """ - count = 0 - to_delete = [] - - for stream_id, stream in self.streams.items(): - if stream.open and (stream_id % 2 == remainder): - count += 1 - elif stream.closed: - to_delete.append(stream_id) - - for stream_id in to_delete: - stream = self.streams.pop(stream_id) - self._closed_streams[stream_id] = stream.closed_by - - return count - - @property - def open_outbound_streams(self) -> int: - """ - The current number of open outbound streams. - """ - outbound_numbers = int(self.config.client_side) - return self._open_streams(outbound_numbers) - - @property - def open_inbound_streams(self) -> int: - """ - The current number of open inbound streams. - """ - inbound_numbers = int(not self.config.client_side) - return self._open_streams(inbound_numbers) - - @property - def inbound_flow_control_window(self) -> int: - """ - The size of the inbound flow control window for the connection. This is - rarely publicly useful: instead, use :meth:`remote_flow_control_window - `. This - shortcut is largely present to provide a shortcut to this data. - """ - return self._inbound_flow_control_window_manager.current_window_size - - def _begin_new_stream(self, stream_id: int, allowed_ids: AllowedStreamIDs) -> H2Stream: - """ - Initiate a new stream. - - .. versionchanged:: 2.0.0 - Removed this function from the public API. - - :param stream_id: The ID of the stream to open. - :param allowed_ids: What kind of stream ID is allowed. - """ - self.config.logger.debug( - "Attempting to initiate stream ID %d", stream_id, - ) - outbound = self._stream_id_is_outbound(stream_id) - highest_stream_id = ( - self.highest_outbound_stream_id if outbound else - self.highest_inbound_stream_id - ) - - if stream_id <= highest_stream_id: - raise StreamIDTooLowError(stream_id, highest_stream_id) - - if (stream_id % 2) != int(allowed_ids): - msg = "Invalid stream ID for peer." - raise ProtocolError(msg) - - s = H2Stream( - stream_id, - config=self.config, - inbound_window_size=self.local_settings.initial_window_size, - outbound_window_size=self.remote_settings.initial_window_size, - ) - self.config.logger.debug("Stream ID %d created", stream_id) - s.max_outbound_frame_size = self.max_outbound_frame_size - - self.streams[stream_id] = s - self.config.logger.debug("Current streams: %s", self.streams.keys()) - - if outbound: - self.highest_outbound_stream_id = stream_id - else: - self.highest_inbound_stream_id = stream_id - - return s - - def initiate_connection(self) -> None: - """ - Provides any data that needs to be sent at the start of the connection. - Must be called for both clients and servers. - """ - self.config.logger.debug("Initializing connection") - self.state_machine.process_input(ConnectionInputs.SEND_SETTINGS) - if self.config.client_side: - preamble = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" - else: - preamble = b"" - - f = SettingsFrame(0) - for setting, value in self.local_settings.items(): - f.settings[setting] = value - self.config.logger.debug( - "Send Settings frame: %s", self.local_settings, - ) - - self._data_to_send += preamble + f.serialize() - - def initiate_upgrade_connection(self, settings_header: bytes | None = None) -> bytes | None: - """ - Call to initialise the connection object for use with an upgraded - HTTP/2 connection (i.e. a connection negotiated using the - ``Upgrade: h2c`` HTTP header). - - This method differs from :meth:`initiate_connection - ` in several ways. - Firstly, it handles the additional SETTINGS frame that is sent in the - ``HTTP2-Settings`` header field. When called on a client connection, - this method will return a bytestring that the caller can put in the - ``HTTP2-Settings`` field they send on their initial request. When - called on a server connection, the user **must** provide the value they - received from the client in the ``HTTP2-Settings`` header field to the - ``settings_header`` argument, which will be used appropriately. - - Additionally, this method sets up stream 1 in a half-closed state - appropriate for this side of the connection, to reflect the fact that - the request is already complete. - - Finally, this method also prepares the appropriate preamble to be sent - after the upgrade. - - .. versionadded:: 2.3.0 - - :param settings_header: (optional, server-only): The value of the - ``HTTP2-Settings`` header field received from the client. - :type settings_header: ``bytes`` - - :returns: For clients, a bytestring to put in the ``HTTP2-Settings``. - For servers, returns nothing. - :rtype: ``bytes`` or ``None`` - """ - self.config.logger.debug( - "Upgrade connection. Current settings: %s", self.local_settings, - ) - - frame_data = None - # Begin by getting the preamble in place. - self.initiate_connection() - - if self.config.client_side: - f = SettingsFrame(0) - for setting, value in self.local_settings.items(): - f.settings[setting] = value - - frame_data = f.serialize_body() - frame_data = base64.urlsafe_b64encode(frame_data) - elif settings_header: - # We have a settings header from the client. This needs to be - # applied, but we want to throw away the ACK. We do this by - # inserting the data into a Settings frame and then passing it to - # the state machine, but ignoring the return value. - settings_header = base64.urlsafe_b64decode(settings_header) - f = SettingsFrame(0) - f.parse_body(memoryview(settings_header)) - self._receive_settings_frame(f) - - # Set up appropriate state. Stream 1 in a half-closed state: - # half-closed(local) for clients, half-closed(remote) for servers. - # Additionally, we need to set up the Connection state machine. - connection_input = ( - ConnectionInputs.SEND_HEADERS if self.config.client_side - else ConnectionInputs.RECV_HEADERS - ) - self.config.logger.debug("Process input %s", connection_input) - self.state_machine.process_input(connection_input) - - # Set up stream 1. - self._begin_new_stream(stream_id=1, allowed_ids=AllowedStreamIDs.ODD) - self.streams[1].upgrade(self.config.client_side) - return frame_data - - def _get_or_create_stream(self, stream_id: int, allowed_ids: AllowedStreamIDs) -> H2Stream: - """ - Gets a stream by its stream ID. Will create one if one does not already - exist. Use allowed_ids to circumvent the usual stream ID rules for - clients and servers. - - .. versionchanged:: 2.0.0 - Removed this function from the public API. - """ - try: - return self.streams[stream_id] - except KeyError: - return self._begin_new_stream(stream_id, allowed_ids) - - def _get_stream_by_id(self, stream_id: int | None) -> H2Stream: - """ - Gets a stream by its stream ID. Raises NoSuchStreamError if the stream - ID does not correspond to a known stream and is higher than the current - maximum: raises if it is lower than the current maximum. - - .. versionchanged:: 2.0.0 - Removed this function from the public API. - """ - if not stream_id: - raise NoSuchStreamError(-1) # pragma: no cover - try: - return self.streams[stream_id] - except KeyError as e: - outbound = self._stream_id_is_outbound(stream_id) - highest_stream_id = ( - self.highest_outbound_stream_id if outbound else - self.highest_inbound_stream_id - ) - - if stream_id > highest_stream_id: - raise NoSuchStreamError(stream_id) from e - raise StreamClosedError(stream_id) from e - - def get_next_available_stream_id(self) -> int: - """ - Returns an integer suitable for use as the stream ID for the next - stream created by this endpoint. For server endpoints, this stream ID - will be even. For client endpoints, this stream ID will be odd. If no - stream IDs are available, raises :class:`NoAvailableStreamIDError - `. - - .. warning:: The return value from this function does not change until - the stream ID has actually been used by sending or pushing - headers on that stream. For that reason, it should be - called as close as possible to the actual use of the - stream ID. - - .. versionadded:: 2.0.0 - - :raises: :class:`NoAvailableStreamIDError - ` - :returns: The next free stream ID this peer can use to initiate a - stream. - :rtype: ``int`` - """ - # No streams have been opened yet, so return the lowest allowed stream - # ID. - if not self.highest_outbound_stream_id: - next_stream_id = 1 if self.config.client_side else 2 - else: - next_stream_id = self.highest_outbound_stream_id + 2 - self.config.logger.debug( - "Next available stream ID %d", next_stream_id, - ) - if next_stream_id > self.HIGHEST_ALLOWED_STREAM_ID: - msg = "Exhausted allowed stream IDs" - raise NoAvailableStreamIDError(msg) - - return next_stream_id - - def send_headers(self, - stream_id: int, - headers: Iterable[HeaderWeaklyTyped], - end_stream: bool = False, - priority_weight: int | None = None, - priority_depends_on: int | None = None, - priority_exclusive: bool | None = None) -> None: - """ - Send headers on a given stream. - - This function can be used to send request or response headers: the kind - that are sent depends on whether this connection has been opened as a - client or server connection, and whether the stream was opened by the - remote peer or not. - - If this is a client connection, calling ``send_headers`` will send the - headers as a request. It will also implicitly open the stream being - used. If this is a client connection and ``send_headers`` has *already* - been called, this will send trailers instead. - - If this is a server connection, calling ``send_headers`` will send the - headers as a response. It is a protocol error for a server to open a - stream by sending headers. If this is a server connection and - ``send_headers`` has *already* been called, this will send trailers - instead. - - When acting as a server, you may call ``send_headers`` any number of - times allowed by the following rules, in this order: - - - zero or more times with ``(':status', '1XX')`` (where ``1XX`` is a - placeholder for any 100-level status code). - - once with any other status header. - - zero or one time for trailers. - - That is, you are allowed to send as many informational responses as you - like, followed by one complete response and zero or one HTTP trailer - blocks. - - Clients may send one or two header blocks: one request block, and - optionally one trailer block. - - If it is important to send HPACK "never indexed" header fields (as - defined in `RFC 7451 Section 7.1.3 - `_), the user may - instead provide headers using the HPACK library's :class:`HeaderTuple - ` and :class:`NeverIndexedHeaderTuple - ` objects. - - This method also allows users to prioritize the stream immediately, - by sending priority information on the HEADERS frame directly. To do - this, any one of ``priority_weight``, ``priority_depends_on``, or - ``priority_exclusive`` must be set to a value that is not ``None``. For - more information on the priority fields, see :meth:`prioritize - `. - - .. warning:: In HTTP/2, it is mandatory that all the HTTP/2 special - headers (that is, ones whose header keys begin with ``:``) appear - at the start of the header block, before any normal headers. - - .. versionchanged:: 2.3.0 - Added support for using :class:`HeaderTuple - ` objects to store headers. - - .. versionchanged:: 2.4.0 - Added the ability to provide priority keyword arguments: - ``priority_weight``, ``priority_depends_on``, and - ``priority_exclusive``. - - :param stream_id: The stream ID to send the headers on. If this stream - does not currently exist, it will be created. - :type stream_id: ``int`` - - :param headers: The request/response headers to send. - :type headers: An iterable of two tuples of bytestrings or - :class:`HeaderTuple ` objects. - - :param end_stream: Whether this headers frame should end the stream - immediately (that is, whether no more data will be sent after this - frame). Defaults to ``False``. - :type end_stream: ``bool`` - - :param priority_weight: Sets the priority weight of the stream. See - :meth:`prioritize ` for more - about how this field works. Defaults to ``None``, which means that - no priority information will be sent. - :type priority_weight: ``int`` or ``None`` - - :param priority_depends_on: Sets which stream this one depends on for - priority purposes. See :meth:`prioritize - ` for more about how this - field works. Defaults to ``None``, which means that no priority - information will be sent. - :type priority_depends_on: ``int`` or ``None`` - - :param priority_exclusive: Sets whether this stream exclusively depends - on the stream given in ``priority_depends_on`` for priority - purposes. See :meth:`prioritize - ` for more about how this - field workds. Defaults to ``None``, which means that no priority - information will be sent. - :type priority_depends_on: ``bool`` or ``None`` - - :returns: Nothing - """ - self.config.logger.debug( - "Send headers on stream ID %d", stream_id, - ) - - # Check we can open the stream. - if stream_id not in self.streams: - max_open_streams = self.remote_settings.max_concurrent_streams - if (self.open_outbound_streams + 1) > max_open_streams: - msg = f"Max outbound streams is {max_open_streams}, {self.open_outbound_streams} open" - raise TooManyStreamsError(msg) - - self.state_machine.process_input(ConnectionInputs.SEND_HEADERS) - stream = self._get_or_create_stream( - stream_id, AllowedStreamIDs(self.config.client_side), - ) - - frames: list[Frame] = [] - frames.extend(stream.send_headers( - headers, self.encoder, end_stream, - )) - - # We may need to send priority information. - priority_present = ( - (priority_weight is not None) or - (priority_depends_on is not None) or - (priority_exclusive is not None) - ) - - if priority_present: - if not self.config.client_side: - msg = "Servers SHOULD NOT prioritize streams." - raise RFC1122Error(msg) - - headers_frame = frames[0] - assert isinstance(headers_frame, HeadersFrame) - - headers_frame.flags.add("PRIORITY") - frames[0] = _add_frame_priority( - headers_frame, - priority_weight, - priority_depends_on, - priority_exclusive, - ) - - self._prepare_for_sending(frames) - - def send_data(self, - stream_id: int, - data: bytes | memoryview, - end_stream: bool = False, - pad_length: Any = None) -> None: - """ - Send data on a given stream. - - This method does no breaking up of data: if the data is larger than the - value returned by :meth:`local_flow_control_window - ` for this stream - then a :class:`FlowControlError ` will - be raised. If the data is larger than :data:`max_outbound_frame_size - ` then a - :class:`FrameTooLargeError ` will be - raised. - - h2 does this to avoid buffering the data internally. If the user - has more data to send than h2 will allow, consider breaking it up - and buffering it externally. - - :param stream_id: The ID of the stream on which to send the data. - :type stream_id: ``int`` - :param data: The data to send on the stream. - :type data: ``bytes`` - :param end_stream: (optional) Whether this is the last data to be sent - on the stream. Defaults to ``False``. - :type end_stream: ``bool`` - :param pad_length: (optional) Length of the padding to apply to the - data frame. Defaults to ``None`` for no use of padding. Note that - a value of ``0`` results in padding of length ``0`` - (with the "padding" flag set on the frame). - - .. versionadded:: 2.6.0 - - :type pad_length: ``int`` - :returns: Nothing - """ - self.config.logger.debug( - "Send data on stream ID %d with len %d", stream_id, len(data), - ) - frame_size = len(data) - if pad_length is not None: - if not isinstance(pad_length, int): - msg = "pad_length must be an int" - raise TypeError(msg) - if pad_length < 0 or pad_length > 255: - msg = "pad_length must be within range: [0, 255]" - raise ValueError(msg) - # Account for padding bytes plus the 1-byte padding length field. - frame_size += pad_length + 1 - self.config.logger.debug( - "Frame size on stream ID %d is %d", stream_id, frame_size, - ) - - if frame_size > self.local_flow_control_window(stream_id): - msg = f"Cannot send {frame_size} bytes, flow control window is {self.local_flow_control_window(stream_id)}" - raise FlowControlError(msg) - if frame_size > self.max_outbound_frame_size: - msg = f"Cannot send frame size {frame_size}, max frame size is {self.max_outbound_frame_size}" - raise FrameTooLargeError(msg) - - self.state_machine.process_input(ConnectionInputs.SEND_DATA) - frames = self.streams[stream_id].send_data( - data, end_stream, pad_length=pad_length, - ) - - self._prepare_for_sending(frames) - - self.outbound_flow_control_window -= frame_size - self.config.logger.debug( - "Outbound flow control window size is %d", - self.outbound_flow_control_window, - ) - assert self.outbound_flow_control_window >= 0 - - def end_stream(self, stream_id: int) -> None: - """ - Cleanly end a given stream. - - This method ends a stream by sending an empty DATA frame on that stream - with the ``END_STREAM`` flag set. - - :param stream_id: The ID of the stream to end. - :type stream_id: ``int`` - :returns: Nothing - """ - self.config.logger.debug("End stream ID %d", stream_id) - self.state_machine.process_input(ConnectionInputs.SEND_DATA) - frames = self.streams[stream_id].end_stream() - self._prepare_for_sending(frames) - - def increment_flow_control_window(self, increment: int, stream_id: int | None = None) -> None: - """ - Increment a flow control window, optionally for a single stream. Allows - the remote peer to send more data. - - .. versionchanged:: 2.0.0 - Rejects attempts to increment the flow control window by out of - range values with a ``ValueError``. - - :param increment: The amount to increment the flow control window by. - :type increment: ``int`` - :param stream_id: (optional) The ID of the stream that should have its - flow control window opened. If not present or ``None``, the - connection flow control window will be opened instead. - :type stream_id: ``int`` or ``None`` - :returns: Nothing - :raises: ``ValueError`` - """ - if not (1 <= increment <= self.MAX_WINDOW_INCREMENT): - msg = f"Flow control increment must be between 1 and {self.MAX_WINDOW_INCREMENT}" - raise ValueError(msg) - - self.state_machine.process_input(ConnectionInputs.SEND_WINDOW_UPDATE) - - if stream_id is not None: - stream = self.streams[stream_id] - frames = stream.increase_flow_control_window( - increment, - ) - - self.config.logger.debug( - "Increase stream ID %d flow control window by %d", - stream_id, increment, - ) - else: - self._inbound_flow_control_window_manager.window_opened(increment) - f = WindowUpdateFrame(0) - f.window_increment = increment - frames = [f] - - self.config.logger.debug( - "Increase connection flow control window by %d", increment, - ) - - self._prepare_for_sending(frames) - - def push_stream(self, - stream_id: int, - promised_stream_id: int, - request_headers: Iterable[HeaderWeaklyTyped]) -> None: - """ - Push a response to the client by sending a PUSH_PROMISE frame. - - If it is important to send HPACK "never indexed" header fields (as - defined in `RFC 7451 Section 7.1.3 - `_), the user may - instead provide headers using the HPACK library's :class:`HeaderTuple - ` and :class:`NeverIndexedHeaderTuple - ` objects. - - :param stream_id: The ID of the stream that this push is a response to. - :type stream_id: ``int`` - :param promised_stream_id: The ID of the stream that the pushed - response will be sent on. - :type promised_stream_id: ``int`` - :param request_headers: The headers of the request that the pushed - response will be responding to. - :type request_headers: An iterable of two tuples of bytestrings or - :class:`HeaderTuple ` objects. - :returns: Nothing - """ - self.config.logger.debug( - "Send Push Promise frame on stream ID %d", stream_id, - ) - - if not self.remote_settings.enable_push: - msg = "Remote peer has disabled stream push" - raise ProtocolError(msg) - - self.state_machine.process_input(ConnectionInputs.SEND_PUSH_PROMISE) - stream = self._get_stream_by_id(stream_id) - - # We need to prevent users pushing streams in response to streams that - # they themselves have already pushed: see #163 and RFC 7540 § 6.6. The - # easiest way to do that is to assert that the stream_id is not even: - # this shortcut works because only servers can push and the state - # machine will enforce this. - if (stream_id % 2) == 0: - msg = "Cannot recursively push streams." - raise ProtocolError(msg) - - new_stream = self._begin_new_stream( - promised_stream_id, AllowedStreamIDs.EVEN, - ) - self.streams[promised_stream_id] = new_stream - - frames = stream.push_stream_in_band( - promised_stream_id, request_headers, self.encoder, - ) - new_frames = new_stream.locally_pushed() - self._prepare_for_sending(frames + new_frames) - - def ping(self, opaque_data: bytes | str) -> None: - """ - Send a PING frame. - - :param opaque_data: A bytestring of length 8 that will be sent in the - PING frame. - :returns: Nothing - """ - self.config.logger.debug("Send Ping frame") - - if not isinstance(opaque_data, bytes) or len(opaque_data) != 8: - msg = f"Invalid value for ping data: {opaque_data!r}" - raise ValueError(msg) - - self.state_machine.process_input(ConnectionInputs.SEND_PING) - f = PingFrame(0) - f.opaque_data = opaque_data - self._prepare_for_sending([f]) - - def reset_stream(self, stream_id: int, error_code: ErrorCodes | int = 0) -> None: - """ - Reset a stream. - - This method forcibly closes a stream by sending a RST_STREAM frame for - a given stream. This is not a graceful closure. To gracefully end a - stream, try the :meth:`end_stream - ` method. - - :param stream_id: The ID of the stream to reset. - :type stream_id: ``int`` - :param error_code: (optional) The error code to use to reset the - stream. Defaults to :data:`ErrorCodes.NO_ERROR - `. - :type error_code: ``int`` - :returns: Nothing - """ - self.config.logger.debug("Reset stream ID %d", stream_id) - self.state_machine.process_input(ConnectionInputs.SEND_RST_STREAM) - stream = self._get_stream_by_id(stream_id) - frames = stream.reset_stream(error_code) - self._prepare_for_sending(frames) - - def close_connection(self, - error_code: ErrorCodes | int = 0, - additional_data: bytes | None = None, - last_stream_id: int | None = None) -> None: - """ - Close a connection, emitting a GOAWAY frame. - - .. versionchanged:: 2.4.0 - Added ``additional_data`` and ``last_stream_id`` arguments. - - :param error_code: (optional) The error code to send in the GOAWAY - frame. - :param additional_data: (optional) Additional debug data indicating - a reason for closing the connection. Must be a bytestring. - :param last_stream_id: (optional) The last stream which was processed - by the sender. Defaults to ``highest_inbound_stream_id``. - :returns: Nothing - """ - self.config.logger.debug("Close connection") - self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY) - - # Additional_data must be bytes - if additional_data is not None: - assert isinstance(additional_data, bytes) - - if last_stream_id is None: - last_stream_id = self.highest_inbound_stream_id - - f = GoAwayFrame( - stream_id=0, - last_stream_id=last_stream_id, - error_code=error_code, - additional_data=(additional_data or b""), - ) - self._prepare_for_sending([f]) - - def update_settings(self, new_settings: dict[SettingCodes | int, int]) -> None: - """ - Update the local settings. This will prepare and emit the appropriate - SETTINGS frame. - - :param new_settings: A dictionary of {setting: new value} - """ - self.config.logger.debug( - "Update connection settings to %s", new_settings, - ) - self.state_machine.process_input(ConnectionInputs.SEND_SETTINGS) - self.local_settings.update(new_settings) - s = SettingsFrame(0) - s.settings = new_settings - self._prepare_for_sending([s]) - - def advertise_alternative_service(self, - field_value: bytes | str, - origin: bytes | None = None, - stream_id: int | None = None) -> None: - """ - Notify a client about an available Alternative Service. - - An Alternative Service is defined in `RFC 7838 - `_. An Alternative Service - notification informs a client that a given origin is also available - elsewhere. - - Alternative Services can be advertised in two ways. Firstly, they can - be advertised explicitly: that is, a server can say "origin X is also - available at Y". To advertise like this, set the ``origin`` argument - and not the ``stream_id`` argument. Alternatively, they can be - advertised implicitly: that is, a server can say "the origin you're - contacting on stream X is also available at Y". To advertise like this, - set the ``stream_id`` argument and not the ``origin`` argument. - - The explicit method of advertising can be done as long as the - connection is active. The implicit method can only be done after the - client has sent the request headers and before the server has sent the - response headers: outside of those points, h2 will forbid sending - the Alternative Service advertisement by raising a ProtocolError. - - The ``field_value`` parameter is specified in RFC 7838. h2 does - not validate or introspect this argument: the user is required to - ensure that it's well-formed. ``field_value`` corresponds to RFC 7838's - "Alternative Service Field Value". - - .. note:: It is strongly preferred to use the explicit method of - advertising Alternative Services. The implicit method of - advertising Alternative Services has a number of subtleties - and can lead to inconsistencies between the server and - client. h2 allows both mechanisms, but caution is - strongly advised. - - .. versionadded:: 2.3.0 - - :param field_value: The RFC 7838 Alternative Service Field Value. This - argument is not introspected by h2: the user is responsible - for ensuring that it is well-formed. - :type field_value: ``bytes`` - - :param origin: The origin/authority to which the Alternative Service - being advertised applies. Must not be provided at the same time as - ``stream_id``. - :type origin: ``bytes`` or ``None`` - - :param stream_id: The ID of the stream which was sent to the authority - for which this Alternative Service advertisement applies. Must not - be provided at the same time as ``origin``. - :type stream_id: ``int`` or ``None`` - - :returns: Nothing. - """ - if not isinstance(field_value, bytes): - msg = "Field must be bytestring." - raise ValueError(msg) # noqa: TRY004 - - if origin is not None and stream_id is not None: - msg = "Must not provide both origin and stream_id" - raise ValueError(msg) - - self.state_machine.process_input( - ConnectionInputs.SEND_ALTERNATIVE_SERVICE, - ) - - if origin is not None: - # This ALTSVC is sent on stream zero. - f = AltSvcFrame(stream_id=0) - f.origin = origin - f.field = field_value - frames: list[Frame] = [f] - else: - stream = self._get_stream_by_id(stream_id) - frames = stream.advertise_alternative_service(field_value) - - self._prepare_for_sending(frames) - - def prioritize(self, - stream_id: int, - weight: int | None = None, - depends_on: int | None = None, - exclusive: bool | None = None) -> None: - """ - Notify a server about the priority of a stream. - - Stream priorities are a form of guidance to a remote server: they - inform the server about how important a given response is, so that the - server may allocate its resources (e.g. bandwidth, CPU time, etc.) - accordingly. This exists to allow clients to ensure that the most - important data arrives earlier, while less important data does not - starve out the more important data. - - Stream priorities are explained in depth in `RFC 7540 Section 5.3 - `_. - - This method updates the priority information of a single stream. It may - be called well before a stream is actively in use, or well after a - stream is closed. - - .. warning:: RFC 7540 allows for servers to change the priority of - streams. However, h2 **does not** allow server - stacks to do this. This is because most clients do not - adequately know how to respond when provided conflicting - priority information, and relatively little utility is - provided by making that functionality available. - - .. note:: h2 **does not** maintain any information about the - RFC 7540 priority tree. That means that h2 does not - prevent incautious users from creating invalid priority - trees, particularly by creating priority loops. While some - basic error checking is provided by h2, users are - strongly recommended to understand their prioritisation - strategies before using the priority tools here. - - .. note:: Priority information is strictly advisory. Servers are - allowed to disregard it entirely. Avoid relying on the idea - that your priority signaling will definitely be obeyed. - - .. versionadded:: 2.4.0 - - :param stream_id: The ID of the stream to prioritize. - :type stream_id: ``int`` - - :param weight: The weight to give the stream. Defaults to ``16``, the - default weight of any stream. May be any value between ``1`` and - ``256`` inclusive. The relative weight of a stream indicates what - proportion of available resources will be allocated to that - stream. - :type weight: ``int`` - - :param depends_on: The ID of the stream on which this stream depends. - This stream will only be progressed if it is impossible to - progress the parent stream (the one on which this one depends). - Passing the value ``0`` means that this stream does not depend on - any other. Defaults to ``0``. - :type depends_on: ``int`` - - :param exclusive: Whether this stream is an exclusive dependency of its - "parent" stream (i.e. the stream given by ``depends_on``). If a - stream is an exclusive dependency of another, that means that all - previously-set children of the parent are moved to become children - of the new exclusively-dependent stream. Defaults to ``False``. - :type exclusive: ``bool`` - """ - if not self.config.client_side: - msg = "Servers SHOULD NOT prioritize streams." - raise RFC1122Error(msg) - - self.state_machine.process_input( - ConnectionInputs.SEND_PRIORITY, - ) - - frame = PriorityFrame(stream_id) - frame_prio = _add_frame_priority(frame, weight, depends_on, exclusive) - - self._prepare_for_sending([frame_prio]) - - def local_flow_control_window(self, stream_id: int) -> int: - """ - Returns the maximum amount of data that can be sent on stream - ``stream_id``. - - This value will never be larger than the total data that can be sent on - the connection: even if the given stream allows more data, the - connection window provides a logical maximum to the amount of data that - can be sent. - - The maximum data that can be sent in a single data frame on a stream - is either this value, or the maximum frame size, whichever is - *smaller*. - - :param stream_id: The ID of the stream whose flow control window is - being queried. - :type stream_id: ``int`` - :returns: The amount of data in bytes that can be sent on the stream - before the flow control window is exhausted. - :rtype: ``int`` - """ - stream = self._get_stream_by_id(stream_id) - return min( - self.outbound_flow_control_window, - stream.outbound_flow_control_window, - ) - - def remote_flow_control_window(self, stream_id: int) -> int: - """ - Returns the maximum amount of data the remote peer can send on stream - ``stream_id``. - - This value will never be larger than the total data that can be sent on - the connection: even if the given stream allows more data, the - connection window provides a logical maximum to the amount of data that - can be sent. - - The maximum data that can be sent in a single data frame on a stream - is either this value, or the maximum frame size, whichever is - *smaller*. - - :param stream_id: The ID of the stream whose flow control window is - being queried. - :type stream_id: ``int`` - :returns: The amount of data in bytes that can be received on the - stream before the flow control window is exhausted. - :rtype: ``int`` - """ - stream = self._get_stream_by_id(stream_id) - return min( - self.inbound_flow_control_window, - stream.inbound_flow_control_window, - ) - - def acknowledge_received_data(self, acknowledged_size: int, stream_id: int) -> None: - """ - Inform the :class:`H2Connection ` that a - certain number of flow-controlled bytes have been processed, and that - the space should be handed back to the remote peer at an opportune - time. - - .. versionadded:: 2.5.0 - - :param acknowledged_size: The total *flow-controlled size* of the data - that has been processed. Note that this must include the amount of - padding that was sent with that data. - :type acknowledged_size: ``int`` - :param stream_id: The ID of the stream on which this data was received. - :type stream_id: ``int`` - :returns: Nothing - :rtype: ``None`` - """ - self.config.logger.debug( - "Ack received data on stream ID %d with size %d", - stream_id, acknowledged_size, - ) - if stream_id <= 0: - msg = f"Stream ID {stream_id} is not valid for acknowledge_received_data" - raise ValueError(msg) - if acknowledged_size < 0: - msg = "Cannot acknowledge negative data" - raise ValueError(msg) - - frames: list[Frame] = [] - - conn_manager = self._inbound_flow_control_window_manager - conn_increment = conn_manager.process_bytes(acknowledged_size) - if conn_increment: - f = WindowUpdateFrame(0) - f.window_increment = conn_increment - frames.append(f) - - try: - stream = self._get_stream_by_id(stream_id) - except StreamClosedError: - # The stream is already gone. We're not worried about incrementing - # the window in this case. - pass - else: - # No point incrementing the windows of closed streams. - if stream.open: - frames.extend( - stream.acknowledge_received_data(acknowledged_size), - ) - - self._prepare_for_sending(frames) - - def data_to_send(self, amount: int | None = None) -> bytes: - """ - Returns some data for sending out of the internal data buffer. - - This method is analogous to ``read`` on a file-like object, but it - doesn't block. Instead, it returns as much data as the user asks for, - or less if that much data is not available. It does not perform any - I/O, and so uses a different name. - - :param amount: (optional) The maximum amount of data to return. If not - set, or set to ``None``, will return as much data as possible. - :type amount: ``int`` - :returns: A bytestring containing the data to send on the wire. - :rtype: ``bytes`` - """ - if amount is None: - data = bytes(self._data_to_send) - self._data_to_send = bytearray() - return data - data = bytes(self._data_to_send[:amount]) - self._data_to_send = self._data_to_send[amount:] - return data - - def clear_outbound_data_buffer(self) -> None: - """ - Clears the outbound data buffer, such that if this call was immediately - followed by a call to - :meth:`data_to_send `, that - call would return no data. - - This method should not normally be used, but is made available to avoid - exposing implementation details. - """ - self._data_to_send = bytearray() - - def _acknowledge_settings(self) -> list[Frame]: - """ - Acknowledge settings that have been received. - - .. versionchanged:: 2.0.0 - Removed from public API, removed useless ``event`` parameter, made - automatic. - - :returns: Nothing - """ - self.state_machine.process_input(ConnectionInputs.SEND_SETTINGS) - - changes = self.remote_settings.acknowledge() - - if SettingCodes.INITIAL_WINDOW_SIZE in changes: - setting = changes[SettingCodes.INITIAL_WINDOW_SIZE] - self._flow_control_change_from_settings( - setting.original_value, - setting.new_value, - ) - - # HEADER_TABLE_SIZE changes by the remote part affect our encoder: cf. - # RFC 7540 Section 6.5.2. - if SettingCodes.HEADER_TABLE_SIZE in changes: - setting = changes[SettingCodes.HEADER_TABLE_SIZE] - self.encoder.header_table_size = setting.new_value - - if SettingCodes.MAX_FRAME_SIZE in changes: - setting = changes[SettingCodes.MAX_FRAME_SIZE] - self.max_outbound_frame_size = setting.new_value - for stream in self.streams.values(): - stream.max_outbound_frame_size = setting.new_value - - f = SettingsFrame(0) - f.flags.add("ACK") - return [f] - - def _flow_control_change_from_settings(self, old_value: int | None, new_value: int) -> None: - """ - Update flow control windows in response to a change in the value of - SETTINGS_INITIAL_WINDOW_SIZE. - - When this setting is changed, it automatically updates all flow control - windows by the delta in the settings values. Note that it does not - increment the *connection* flow control window, per section 6.9.2 of - RFC 7540. - """ - delta = new_value - (old_value or 0) - - for stream in self.streams.values(): - stream.outbound_flow_control_window = guard_increment_window( - stream.outbound_flow_control_window, - delta, - ) - - def _inbound_flow_control_change_from_settings(self, old_value: int | None, new_value: int) -> None: - """ - Update remote flow control windows in response to a change in the value - of SETTINGS_INITIAL_WINDOW_SIZE. - - When this setting is changed, it automatically updates all remote flow - control windows by the delta in the settings values. - """ - delta = new_value - (old_value or 0) - - for stream in self.streams.values(): - stream._inbound_flow_control_change_from_settings(delta) - - def receive_data(self, data: bytes) -> list[Event]: - """ - Pass some received HTTP/2 data to the connection for handling. - - :param data: The data received from the remote peer on the network. - :type data: ``bytes`` - :returns: A list of events that the remote peer triggered by sending - this data. - """ - self.config.logger.trace( - "Process received data on connection. Received data: %r", data, - ) - - events: list[Event] = [] - self.incoming_buffer.add_data(data) - self.incoming_buffer.max_frame_size = self.max_inbound_frame_size - - try: - for frame in self.incoming_buffer: - events.extend(self._receive_frame(frame)) - except InvalidPaddingError as e: - self._terminate_connection(ErrorCodes.PROTOCOL_ERROR) - msg = "Received frame with invalid padding." - raise ProtocolError(msg) from e - except ProtocolError as e: - # For whatever reason, receiving the frame caused a protocol error. - # We should prepare to emit a GoAway frame before throwing the - # exception up further. No need for an event: the exception will - # do fine. - self._terminate_connection(e.error_code) - raise - - return events - - def _receive_frame(self, frame: Frame) -> list[Event]: - """ - Handle a frame received on the connection. - - .. versionchanged:: 2.0.0 - Removed from the public API. - """ - events: list[Event] - self.config.logger.trace("Received frame: %s", repr(frame)) - try: - # I don't love using __class__ here, maybe reconsider it. - frames, events = self._frame_dispatch_table[frame.__class__](frame) - except StreamClosedError as e: - # If the stream was closed by RST_STREAM, we just send a RST_STREAM - # to the remote peer. Otherwise, this is a connection error, and so - # we will re-raise to trigger one. - if self._stream_is_closed_by_reset(e.stream_id): - f = RstStreamFrame(e.stream_id) - f.error_code = e.error_code - self._prepare_for_sending([f]) - events = e._events - else: - raise - except StreamIDTooLowError as e: - # The stream ID seems invalid. This may happen when the closed - # stream has been cleaned up, or when the remote peer has opened a - # new stream with a higher stream ID than this one, forcing it - # closed implicitly. - # - # Check how the stream was closed: depending on the mechanism, it - # is either a stream error or a connection error. - if self._stream_is_closed_by_reset(e.stream_id): - # Closed by RST_STREAM is a stream error. - f = RstStreamFrame(e.stream_id) - f.error_code = ErrorCodes.STREAM_CLOSED - self._prepare_for_sending([f]) - events = [] - elif self._stream_is_closed_by_end(e.stream_id): - # Closed by END_STREAM is a connection error. - raise StreamClosedError(e.stream_id) from e - else: - # Closed implicitly, also a connection error, but of type - # PROTOCOL_ERROR. - raise - else: - self._prepare_for_sending(frames) - - return events - - def _terminate_connection(self, error_code: ErrorCodes) -> None: - """ - Terminate the connection early. Used in error handling blocks to send - GOAWAY frames. - """ - f = GoAwayFrame(0) - f.last_stream_id = self.highest_inbound_stream_id - f.error_code = error_code - self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY) - self._prepare_for_sending([f]) - - def _receive_headers_frame(self, frame: HeadersFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a headers frame on the connection. - """ - # If necessary, check we can open the stream. Also validate that the - # stream ID is valid. - if frame.stream_id not in self.streams: - max_open_streams = self.local_settings.max_concurrent_streams - if (self.open_inbound_streams + 1) > max_open_streams: - msg = f"Max outbound streams is {max_open_streams}, {self.open_outbound_streams} open" - raise TooManyStreamsError(msg) - - # Let's decode the headers. We handle headers as bytes internally up - # until we hang them off the event, at which point we may optionally - # convert them to unicode. - headers = _decode_headers(self.decoder, frame.data) - - events = self.state_machine.process_input( - ConnectionInputs.RECV_HEADERS, - ) - stream = self._get_or_create_stream( - frame.stream_id, AllowedStreamIDs(not self.config.client_side), - ) - frames, stream_events = stream.receive_headers( - headers, - "END_STREAM" in frame.flags, - self.config.header_encoding, - ) - - if "PRIORITY" in frame.flags: - p_frames, p_events = self._receive_priority_frame(frame) - expected_frame_types = (RequestReceived, ResponseReceived, TrailersReceived, InformationalResponseReceived) - assert isinstance(stream_events[0], expected_frame_types) - assert isinstance(p_events[0], PriorityUpdated) - stream_events[0].priority_updated = p_events[0] - stream_events.extend(p_events) - assert not p_frames - - return frames, events + stream_events - - def _receive_push_promise_frame(self, frame: PushPromiseFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a push-promise frame on the connection. - """ - if not self.local_settings.enable_push: - msg = "Received pushed stream" - raise ProtocolError(msg) - - pushed_headers = _decode_headers(self.decoder, frame.data) - - events = self.state_machine.process_input( - ConnectionInputs.RECV_PUSH_PROMISE, - ) - - try: - stream = self._get_stream_by_id(frame.stream_id) - except NoSuchStreamError as e: - # We need to check if the parent stream was reset by us. If it was - # then we presume that the PUSH_PROMISE was in flight when we reset - # the parent stream. Rather than accept the new stream, just reset - # it. - # - # If this was closed naturally, however, we should call this a - # PROTOCOL_ERROR: pushing a stream on a naturally closed stream is - # a real problem because it creates a brand new stream that the - # remote peer now believes exists. - if (self._stream_closed_by(frame.stream_id) == - StreamClosedBy.SEND_RST_STREAM): - f = RstStreamFrame(frame.promised_stream_id) - f.error_code = ErrorCodes.REFUSED_STREAM - return [f], events - - msg = "Attempted to push on closed stream." - raise ProtocolError(msg) from e - - # We need to prevent peers pushing streams in response to streams that - # they themselves have already pushed: see #163 and RFC 7540 § 6.6. The - # easiest way to do that is to assert that the stream_id is not even: - # this shortcut works because only servers can push and the state - # machine will enforce this. - if (frame.stream_id % 2) == 0: - msg = "Cannot recursively push streams." - raise ProtocolError(msg) - - try: - frames, stream_events = stream.receive_push_promise_in_band( - frame.promised_stream_id, - pushed_headers, - self.config.header_encoding, - ) - except StreamClosedError: - # The parent stream was reset by us, so we presume that - # PUSH_PROMISE was in flight when we reset the parent stream. - # So we just reset the new stream. - f = RstStreamFrame(frame.promised_stream_id) - f.error_code = ErrorCodes.REFUSED_STREAM - return [f], events - - new_stream = self._begin_new_stream( - frame.promised_stream_id, AllowedStreamIDs.EVEN, - ) - self.streams[frame.promised_stream_id] = new_stream - new_stream.remotely_pushed(pushed_headers) - - return frames, events + stream_events - - def _handle_data_on_closed_stream(self, - events: list[Event], - exc: StreamClosedError, - frame: DataFrame) -> tuple[list[Frame], list[Event]]: - # This stream is already closed - and yet we received a DATA frame. - # The received DATA frame counts towards the connection flow window. - # We need to manually to acknowledge the DATA frame to update the flow - # window of the connection. Otherwise the whole connection stalls due - # the inbound flow window being 0. - frames: list[Frame] = [] - conn_manager = self._inbound_flow_control_window_manager - conn_increment = conn_manager.process_bytes( - frame.flow_controlled_length, - ) - - if conn_increment: - window_update_frame = WindowUpdateFrame(0) - window_update_frame.window_increment = conn_increment - frames.append(window_update_frame) - self.config.logger.debug( - "Received DATA frame on closed stream %d - " - "auto-emitted a WINDOW_UPDATE by %d", - frame.stream_id, conn_increment, - ) - - rst_stream_frame = RstStreamFrame(exc.stream_id) - rst_stream_frame.error_code = exc.error_code - frames.append(rst_stream_frame) - self.config.logger.debug( - "Stream %s already CLOSED or cleaned up - auto-emitted a RST_FRAME", - frame.stream_id, - ) - return frames, events + exc._events - - def _receive_data_frame(self, frame: DataFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a data frame on the connection. - """ - flow_controlled_length = frame.flow_controlled_length - - events = self.state_machine.process_input( - ConnectionInputs.RECV_DATA, - ) - self._inbound_flow_control_window_manager.window_consumed( - flow_controlled_length, - ) - - try: - stream = self._get_stream_by_id(frame.stream_id) - frames, stream_events = stream.receive_data( - frame.data, - "END_STREAM" in frame.flags, - flow_controlled_length, - ) - except StreamClosedError as e: - # This stream is either marked as CLOSED or already gone from our - # internal state. - return self._handle_data_on_closed_stream(events, e, frame) - - return frames, events + stream_events - - def _receive_settings_frame(self, frame: SettingsFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a SETTINGS frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_SETTINGS, - ) - - # This is an ack of the local settings. - if "ACK" in frame.flags: - changed_settings = self._local_settings_acked() - ack_event = SettingsAcknowledged() - ack_event.changed_settings = changed_settings - events.append(ack_event) - return [], events - - # Add the new settings. - self.remote_settings.update(frame.settings) - events.append( - RemoteSettingsChanged.from_settings( - self.remote_settings, frame.settings, - ), - ) - frames = self._acknowledge_settings() - - return frames, events - - def _receive_window_update_frame(self, frame: WindowUpdateFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a WINDOW_UPDATE frame on the connection. - """ - # hyperframe will take care of validating the window_increment. - # If we reach in here, we can assume a valid value. - - events = self.state_machine.process_input( - ConnectionInputs.RECV_WINDOW_UPDATE, - ) - - if frame.stream_id: - try: - stream = self._get_stream_by_id(frame.stream_id) - frames, stream_events = stream.receive_window_update( - frame.window_increment, - ) - except StreamClosedError: - return [], events - else: - # Increment our local flow control window. - self.outbound_flow_control_window = guard_increment_window( - self.outbound_flow_control_window, - frame.window_increment, - ) - - # FIXME: Should we split this into one event per active stream? - window_updated_event = WindowUpdated() - window_updated_event.stream_id = 0 - window_updated_event.delta = frame.window_increment - stream_events = [window_updated_event] - frames = [] - - return frames, events + stream_events - - def _receive_ping_frame(self, frame: PingFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a PING frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_PING, - ) - frames: list[Frame] = [] - - evt: PingReceived | PingAckReceived - if "ACK" in frame.flags: - evt = PingAckReceived() - else: - evt = PingReceived() - - # automatically ACK the PING with the same 'opaque data' - f = PingFrame(0) - f.flags.add("ACK") - f.opaque_data = frame.opaque_data - frames.append(f) - - evt.ping_data = frame.opaque_data - events.append(evt) - - return frames, events - - def _receive_rst_stream_frame(self, frame: RstStreamFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a RST_STREAM frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_RST_STREAM, - ) - try: - stream = self._get_stream_by_id(frame.stream_id) - except NoSuchStreamError: - # The stream is missing. That's ok, we just do nothing here. - stream_frames: list[Frame] = [] - stream_events: list[Event] = [] - else: - stream_frames, stream_events = stream.stream_reset(frame) - - return stream_frames, events + stream_events - - def _receive_priority_frame(self, frame: HeadersFrame | PriorityFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a PRIORITY frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_PRIORITY, - ) - - event = PriorityUpdated() - event.stream_id = frame.stream_id - event.depends_on = frame.depends_on - event.exclusive = frame.exclusive - - # Weight is an integer between 1 and 256, but the byte only allows - # 0 to 255: add one. - event.weight = frame.stream_weight + 1 - - # A stream may not depend on itself. - if event.depends_on == frame.stream_id: - msg = f"Stream {frame.stream_id} may not depend on itself" - raise ProtocolError(msg) - events.append(event) - - return [], events - - def _receive_goaway_frame(self, frame: GoAwayFrame) -> tuple[list[Frame], list[Event]]: - """ - Receive a GOAWAY frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_GOAWAY, - ) - - # Clear the outbound data buffer: we cannot send further data now. - self.clear_outbound_data_buffer() - - # Fire an appropriate ConnectionTerminated event. - new_event = ConnectionTerminated() - new_event.error_code = _error_code_from_int(frame.error_code) - new_event.last_stream_id = frame.last_stream_id - new_event.additional_data = (frame.additional_data - if frame.additional_data else None) - events.append(new_event) - - return [], events - - def _receive_naked_continuation(self, frame: ContinuationFrame) -> None: - """ - A naked CONTINUATION frame has been received. This is always an error, - but the type of error it is depends on the state of the stream and must - transition the state of the stream, so we need to pass it to the - appropriate stream. - """ - stream = self._get_stream_by_id(frame.stream_id) - stream.receive_continuation() - msg = "Should not be reachable" # pragma: no cover - raise AssertionError(msg) # pragma: no cover - - def _receive_alt_svc_frame(self, frame: AltSvcFrame) -> tuple[list[Frame], list[Event]]: - """ - An ALTSVC frame has been received. This frame, specified in RFC 7838, - is used to advertise alternative places where the same service can be - reached. - - This frame can optionally be received either on a stream or on stream - 0, and its semantics are different in each case. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_ALTERNATIVE_SERVICE, - ) - frames = [] - - if frame.stream_id: - # Given that it makes no sense to receive ALTSVC on a stream - # before that stream has been opened with a HEADERS frame, the - # ALTSVC frame cannot create a stream. If the stream is not - # present, we simply ignore the frame. - try: - stream = self._get_stream_by_id(frame.stream_id) - except (NoSuchStreamError, StreamClosedError): - pass - else: - stream_frames, stream_events = stream.receive_alt_svc(frame) - frames.extend(stream_frames) - events.extend(stream_events) - else: - # This frame is sent on stream 0. The origin field on the frame - # must be present, though if it isn't it's not a ProtocolError - # (annoyingly), we just need to ignore it. - if not frame.origin: - return frames, events - - # If we're a server, we want to ignore this (RFC 7838 says so). - if not self.config.client_side: - return frames, events - - event = AlternativeServiceAvailable() - event.origin = frame.origin - event.field_value = frame.field - events.append(event) - - return frames, events - - def _receive_unknown_frame(self, frame: ExtensionFrame) -> tuple[list[Frame], list[Event]]: - """ - We have received a frame that we do not understand. This is almost - certainly an extension frame, though it's impossible to be entirely - sure. - - RFC 7540 § 5.5 says that we MUST ignore unknown frame types: so we - do. We do notify the user that we received one, however. - """ - # All we do here is log. - self.config.logger.debug( - "Received unknown extension frame (ID %d)", frame.stream_id, - ) - event = UnknownFrameReceived() - event.frame = frame - return [], [event] - - def _local_settings_acked(self) -> dict[SettingCodes | int, ChangedSetting]: - """ - Handle the local settings being ACKed, update internal state. - """ - changes = self.local_settings.acknowledge() - - if SettingCodes.INITIAL_WINDOW_SIZE in changes: - setting = changes[SettingCodes.INITIAL_WINDOW_SIZE] - self._inbound_flow_control_change_from_settings( - setting.original_value, - setting.new_value, - ) - - if SettingCodes.MAX_HEADER_LIST_SIZE in changes: - setting = changes[SettingCodes.MAX_HEADER_LIST_SIZE] - self.decoder.max_header_list_size = setting.new_value - - if SettingCodes.MAX_FRAME_SIZE in changes: - setting = changes[SettingCodes.MAX_FRAME_SIZE] - self.max_inbound_frame_size = setting.new_value - - if SettingCodes.HEADER_TABLE_SIZE in changes: - setting = changes[SettingCodes.HEADER_TABLE_SIZE] - # This is safe across all hpack versions: some versions just won't - # respect it. - self.decoder.max_allowed_table_size = setting.new_value - - return changes - - def _stream_id_is_outbound(self, stream_id: int) -> bool: - """ - Returns ``True`` if the stream ID corresponds to an outbound stream - (one initiated by this peer), returns ``False`` otherwise. - """ - return (stream_id % 2 == int(self.config.client_side)) - - def _stream_closed_by(self, stream_id: int) -> StreamClosedBy | None: - """ - Returns how the stream was closed. - - The return value will be either a member of - ``h2.stream.StreamClosedBy`` or ``None``. If ``None``, the stream was - closed implicitly by the peer opening a stream with a higher stream ID - before opening this one. - """ - if stream_id in self.streams: - return self.streams[stream_id].closed_by - if stream_id in self._closed_streams: - return self._closed_streams[stream_id] - return None - - def _stream_is_closed_by_reset(self, stream_id: int) -> bool: - """ - Returns ``True`` if the stream was closed by sending or receiving a - RST_STREAM frame. Returns ``False`` otherwise. - """ - return self._stream_closed_by(stream_id) in ( - StreamClosedBy.RECV_RST_STREAM, StreamClosedBy.SEND_RST_STREAM, - ) - - def _stream_is_closed_by_end(self, stream_id: int) -> bool: - """ - Returns ``True`` if the stream was closed by sending or receiving an - END_STREAM flag in a HEADERS or DATA frame. Returns ``False`` - otherwise. - """ - return self._stream_closed_by(stream_id) in ( - StreamClosedBy.RECV_END_STREAM, StreamClosedBy.SEND_END_STREAM, - ) - - -def _add_frame_priority(frame: PriorityFrame | HeadersFrame, - weight: int | None = None, - depends_on: int | None = None, - exclusive: bool | None = None) -> PriorityFrame | HeadersFrame: - """ - Adds priority data to a given frame. Does not change any flags set on that - frame: if the caller is adding priority information to a HEADERS frame they - must set that themselves. - - This method also deliberately sets defaults for anything missing. - - This method validates the input values. - """ - # A stream may not depend on itself. - if depends_on == frame.stream_id: - msg = f"Stream {frame.stream_id} may not depend on itself" - raise ProtocolError(msg) - - # Weight must be between 1 and 256. - if weight is not None: - if weight > 256 or weight < 1: - msg = f"Weight must be between 1 and 256, not {weight}" - raise ProtocolError(msg) - # Weight is an integer between 1 and 256, but the byte only allows - # 0 to 255: subtract one. - weight -= 1 - - # Set defaults for anything not provided. - weight = weight if weight is not None else 15 - depends_on = depends_on if depends_on is not None else 0 - exclusive = exclusive if exclusive is not None else False - - frame.stream_weight = weight - frame.depends_on = depends_on - frame.exclusive = exclusive - - return frame - - -def _decode_headers(decoder: Decoder, encoded_header_block: bytes) -> Iterable[Header]: - """ - Decode a HPACK-encoded header block, translating HPACK exceptions into - sensible h2 errors. - - This only ever returns bytestring headers: h2 may emit them as - unicode later, but internally it processes them as bytestrings only. - """ - try: - return decoder.decode(encoded_header_block, raw=True) - except OversizedHeaderListError as e: - # This is a symptom of a HPACK bomb attack: the user has - # disregarded our requirements on how large a header block we'll - # accept. - msg = f"Oversized header block: {e}" - raise DenialOfServiceError(msg) from e - except (HPACKError, IndexError, TypeError, UnicodeDecodeError) as e: - # We should only need HPACKError here, but versions of HPACK older - # than 2.1.0 throw all three others as well. For maximum - # compatibility, catch all of them. - msg = f"Error decoding header block: {e}" - raise ProtocolError(msg) from e diff --git a/serverenv/lib/python3.9/site-packages/h2/errors.py b/serverenv/lib/python3.9/site-packages/h2/errors.py deleted file mode 100644 index 24ebe00..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/errors.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -h2/errors -~~~~~~~~~ - -Global error code registry containing the established HTTP/2 error codes. - -The current registry is available at: -https://tools.ietf.org/html/rfc7540#section-11.4 -""" -from __future__ import annotations - -import enum - - -class ErrorCodes(enum.IntEnum): - """ - All known HTTP/2 error codes. - - .. versionadded:: 2.5.0 - """ - - #: Graceful shutdown. - NO_ERROR = 0x0 - - #: Protocol error detected. - PROTOCOL_ERROR = 0x1 - - #: Implementation fault. - INTERNAL_ERROR = 0x2 - - #: Flow-control limits exceeded. - FLOW_CONTROL_ERROR = 0x3 - - #: Settings not acknowledged. - SETTINGS_TIMEOUT = 0x4 - - #: Frame received for closed stream. - STREAM_CLOSED = 0x5 - - #: Frame size incorrect. - FRAME_SIZE_ERROR = 0x6 - - #: Stream not processed. - REFUSED_STREAM = 0x7 - - #: Stream cancelled. - CANCEL = 0x8 - - #: Compression state not updated. - COMPRESSION_ERROR = 0x9 - - #: TCP connection error for CONNECT method. - CONNECT_ERROR = 0xa - - #: Processing capacity exceeded. - ENHANCE_YOUR_CALM = 0xb - - #: Negotiated TLS parameters not acceptable. - INADEQUATE_SECURITY = 0xc - - #: Use HTTP/1.1 for the request. - HTTP_1_1_REQUIRED = 0xd - - -def _error_code_from_int(code: int) -> ErrorCodes | int: - """ - Given an integer error code, returns either one of :class:`ErrorCodes - ` or, if not present in the known set of codes, - returns the integer directly. - """ - try: - return ErrorCodes(code) - except ValueError: - return code - - -__all__ = ["ErrorCodes"] diff --git a/serverenv/lib/python3.9/site-packages/h2/events.py b/serverenv/lib/python3.9/site-packages/h2/events.py deleted file mode 100644 index b81fd1a..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/events.py +++ /dev/null @@ -1,639 +0,0 @@ -""" -h2/events -~~~~~~~~~ - -Defines Event types for HTTP/2. - -Events are returned by the H2 state machine to allow implementations to keep -track of events triggered by receiving data. Each time data is provided to the -H2 state machine it processes the data and returns a list of Event objects. -""" -from __future__ import annotations - -import binascii -from typing import TYPE_CHECKING - -from .settings import ChangedSetting, SettingCodes, Settings, _setting_code_from_int - -if TYPE_CHECKING: # pragma: no cover - from hpack import HeaderTuple - from hyperframe.frame import Frame - - from .errors import ErrorCodes - - -class Event: - """ - Base class for h2 events. - """ - - - -class RequestReceived(Event): - """ - The RequestReceived event is fired whenever all of a request's headers - are received. This event carries the HTTP headers for the given request - and the stream ID of the new stream. - - In HTTP/2, headers may be sent as a HEADERS frame followed by zero or more - CONTINUATION frames with the final frame setting the END_HEADERS flag. - This event is fired after the entire sequence is received. - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` and ``priority_updated`` properties. - """ - - def __init__(self) -> None: - #: The Stream ID for the stream this request was made on. - self.stream_id: int | None = None - - #: The request headers. - self.headers: list[HeaderTuple] | None = None - - #: If this request also ended the stream, the associated - #: :class:`StreamEnded ` event will be available - #: here. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended: StreamEnded | None = None - - #: If this request also had associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated: PriorityUpdated | None = None - - def __repr__(self) -> str: - return f"" - - -class ResponseReceived(Event): - """ - The ResponseReceived event is fired whenever response headers are received. - This event carries the HTTP headers for the given response and the stream - ID of the new stream. - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` and ``priority_updated`` properties. - """ - - def __init__(self) -> None: - #: The Stream ID for the stream this response was made on. - self.stream_id: int | None = None - - #: The response headers. - self.headers: list[HeaderTuple] | None = None - - #: If this response also ended the stream, the associated - #: :class:`StreamEnded ` event will be available - #: here. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended: StreamEnded | None = None - - #: If this response also had associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated: PriorityUpdated | None = None - - def __repr__(self) -> str: - return f"" - - -class TrailersReceived(Event): - """ - The TrailersReceived event is fired whenever trailers are received on a - stream. Trailers are a set of headers sent after the body of the - request/response, and are used to provide information that wasn't known - ahead of time (e.g. content-length). This event carries the HTTP header - fields that form the trailers and the stream ID of the stream on which they - were received. - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` and ``priority_updated`` properties. - """ - - def __init__(self) -> None: - #: The Stream ID for the stream on which these trailers were received. - self.stream_id: int | None = None - - #: The trailers themselves. - self.headers: list[HeaderTuple] | None = None - - #: Trailers always end streams. This property has the associated - #: :class:`StreamEnded ` in it. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended: StreamEnded | None = None - - #: If the trailers also set associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated: PriorityUpdated | None = None - - def __repr__(self) -> str: - return f"" - - -class _HeadersSent(Event): - """ - The _HeadersSent event is fired whenever headers are sent. - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - - - -class _ResponseSent(_HeadersSent): - """ - The _ResponseSent event is fired whenever response headers are sent - on a stream. - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - - - -class _RequestSent(_HeadersSent): - """ - The _RequestSent event is fired whenever request headers are sent - on a stream. - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - - - -class _TrailersSent(_HeadersSent): - """ - The _TrailersSent event is fired whenever trailers are sent on a - stream. Trailers are a set of headers sent after the body of the - request/response, and are used to provide information that wasn't known - ahead of time (e.g. content-length). - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - - - -class _PushedRequestSent(_HeadersSent): - """ - The _PushedRequestSent event is fired whenever pushed request headers are - sent. - - This is an internal event, used to determine validation steps on outgoing - header blocks. - """ - - - -class InformationalResponseReceived(Event): - """ - The InformationalResponseReceived event is fired when an informational - response (that is, one whose status code is a 1XX code) is received from - the remote peer. - - The remote peer may send any number of these, from zero upwards. These - responses are most commonly sent in response to requests that have the - ``expect: 100-continue`` header field present. Most users can safely - ignore this event unless you are intending to use the - ``expect: 100-continue`` flow, or are for any reason expecting a different - 1XX status code. - - .. versionadded:: 2.2.0 - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``priority_updated`` property. - """ - - def __init__(self) -> None: - #: The Stream ID for the stream this informational response was made - #: on. - self.stream_id: int | None = None - - #: The headers for this informational response. - self.headers: list[HeaderTuple] | None = None - - #: If this response also had associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated: PriorityUpdated | None = None - - def __repr__(self) -> str: - return f"" - - -class DataReceived(Event): - """ - The DataReceived event is fired whenever data is received on a stream from - the remote peer. The event carries the data itself, and the stream ID on - which the data was received. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` property. - """ - - def __init__(self) -> None: - #: The Stream ID for the stream this data was received on. - self.stream_id: int | None = None - - #: The data itself. - self.data: bytes | None = None - - #: The amount of data received that counts against the flow control - #: window. Note that padding counts against the flow control window, so - #: when adjusting flow control you should always use this field rather - #: than ``len(data)``. - self.flow_controlled_length: int | None = None - - #: If this data chunk also completed the stream, the associated - #: :class:`StreamEnded ` event will be available - #: here. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended: StreamEnded | None = None - - def __repr__(self) -> str: - return ( - "".format( - self.stream_id, - self.flow_controlled_length, - _bytes_representation(self.data[:20]) if self.data else "", - ) - ) - - -class WindowUpdated(Event): - """ - The WindowUpdated event is fired whenever a flow control window changes - size. HTTP/2 defines flow control windows for connections and streams: this - event fires for both connections and streams. The event carries the ID of - the stream to which it applies (set to zero if the window update applies to - the connection), and the delta in the window size. - """ - - def __init__(self) -> None: - #: The Stream ID of the stream whose flow control window was changed. - #: May be ``0`` if the connection window was changed. - self.stream_id: int | None = None - - #: The window delta. - self.delta: int | None = None - - def __repr__(self) -> str: - return f"" - - -class RemoteSettingsChanged(Event): - """ - The RemoteSettingsChanged event is fired whenever the remote peer changes - its settings. It contains a complete inventory of changed settings, - including their previous values. - - In HTTP/2, settings changes need to be acknowledged. h2 automatically - acknowledges settings changes for efficiency. However, it is possible that - the caller may not be happy with the changed setting. - - When this event is received, the caller should confirm that the new - settings are acceptable. If they are not acceptable, the user should close - the connection with the error code :data:`PROTOCOL_ERROR - `. - - .. versionchanged:: 2.0.0 - Prior to this version the user needed to acknowledge settings changes. - This is no longer the case: h2 now automatically acknowledges - them. - """ - - def __init__(self) -> None: - #: A dictionary of setting byte to - #: :class:`ChangedSetting `, representing - #: the changed settings. - self.changed_settings: dict[int, ChangedSetting] = {} - - @classmethod - def from_settings(cls, - old_settings: Settings | dict[int, int], - new_settings: dict[int, int]) -> RemoteSettingsChanged: - """ - Build a RemoteSettingsChanged event from a set of changed settings. - - :param old_settings: A complete collection of old settings, in the form - of a dictionary of ``{setting: value}``. - :param new_settings: All the changed settings and their new values, in - the form of a dictionary of ``{setting: value}``. - """ - e = cls() - for setting, new_value in new_settings.items(): - s = _setting_code_from_int(setting) - original_value = old_settings.get(s) - change = ChangedSetting(s, original_value, new_value) - e.changed_settings[s] = change - - return e - - def __repr__(self) -> str: - return "".format( - ", ".join(repr(cs) for cs in self.changed_settings.values()), - ) - - -class PingReceived(Event): - """ - The PingReceived event is fired whenever a PING is received. It contains - the 'opaque data' of the PING frame. A ping acknowledgment with the same - 'opaque data' is automatically emitted after receiving a ping. - - .. versionadded:: 3.1.0 - """ - - def __init__(self) -> None: - #: The data included on the ping. - self.ping_data: bytes | None = None - - def __repr__(self) -> str: - return f"" - - -class PingAckReceived(Event): - """ - The PingAckReceived event is fired whenever a PING acknowledgment is - received. It contains the 'opaque data' of the PING+ACK frame, allowing the - user to correlate PINGs and calculate RTT. - - .. versionadded:: 3.1.0 - - .. versionchanged:: 4.0.0 - Removed deprecated but equivalent ``PingAcknowledged``. - """ - - def __init__(self) -> None: - #: The data included on the ping. - self.ping_data: bytes | None = None - - def __repr__(self) -> str: - return f"" - - -class StreamEnded(Event): - """ - The StreamEnded event is fired whenever a stream is ended by a remote - party. The stream may not be fully closed if it has not been closed - locally, but no further data or headers should be expected on that stream. - """ - - def __init__(self) -> None: - #: The Stream ID of the stream that was closed. - self.stream_id: int | None = None - - def __repr__(self) -> str: - return f"" - - -class StreamReset(Event): - """ - The StreamReset event is fired in two situations. The first is when the - remote party forcefully resets the stream. The second is when the remote - party has made a protocol error which only affects a single stream. In this - case, h2 will terminate the stream early and return this event. - - .. versionchanged:: 2.0.0 - This event is now fired when h2 automatically resets a stream. - """ - - def __init__(self) -> None: - #: The Stream ID of the stream that was reset. - self.stream_id: int | None = None - - #: The error code given. Either one of :class:`ErrorCodes - #: ` or ``int`` - self.error_code: ErrorCodes | None = None - - #: Whether the remote peer sent a RST_STREAM or we did. - self.remote_reset = True - - def __repr__(self) -> str: - return f"" - - -class PushedStreamReceived(Event): - """ - The PushedStreamReceived event is fired whenever a pushed stream has been - received from a remote peer. The event carries on it the new stream ID, the - ID of the parent stream, and the request headers pushed by the remote peer. - """ - - def __init__(self) -> None: - #: The Stream ID of the stream created by the push. - self.pushed_stream_id: int | None = None - - #: The Stream ID of the stream that the push is related to. - self.parent_stream_id: int | None = None - - #: The request headers, sent by the remote party in the push. - self.headers: list[HeaderTuple] | None = None - - def __repr__(self) -> str: - return ( - f"" - ) - - -class SettingsAcknowledged(Event): - """ - The SettingsAcknowledged event is fired whenever a settings ACK is received - from the remote peer. The event carries on it the settings that were - acknowedged, in the same format as - :class:`h2.events.RemoteSettingsChanged`. - """ - - def __init__(self) -> None: - #: A dictionary of setting byte to - #: :class:`ChangedSetting `, representing - #: the changed settings. - self.changed_settings: dict[SettingCodes | int, ChangedSetting] = {} - - def __repr__(self) -> str: - s = ", ".join(repr(cs) for cs in self.changed_settings.values()) - return f"" - - -class PriorityUpdated(Event): - """ - The PriorityUpdated event is fired whenever a stream sends updated priority - information. This can occur when the stream is opened, or at any time - during the stream lifetime. - - This event is purely advisory, and does not need to be acted on. - - .. versionadded:: 2.0.0 - """ - - def __init__(self) -> None: - #: The ID of the stream whose priority information is being updated. - self.stream_id: int | None = None - - #: The new stream weight. May be the same as the original stream - #: weight. An integer between 1 and 256. - self.weight: int | None = None - - #: The stream ID this stream now depends on. May be ``0``. - self.depends_on: int | None = None - - #: Whether the stream *exclusively* depends on the parent stream. If it - #: does, this stream should inherit the current children of its new - #: parent. - self.exclusive: bool | None = None - - def __repr__(self) -> str: - return ( - f"" - ) - - -class ConnectionTerminated(Event): - """ - The ConnectionTerminated event is fired when a connection is torn down by - the remote peer using a GOAWAY frame. Once received, no further action may - be taken on the connection: a new connection must be established. - """ - - def __init__(self) -> None: - #: The error code cited when tearing down the connection. Should be - #: one of :class:`ErrorCodes `, but may not be if - #: unknown HTTP/2 extensions are being used. - self.error_code: ErrorCodes | int | None = None - - #: The stream ID of the last stream the remote peer saw. This can - #: provide an indication of what data, if any, never reached the remote - #: peer and so can safely be resent. - self.last_stream_id: int | None = None - - #: Additional debug data that can be appended to GOAWAY frame. - self.additional_data: bytes | None = None - - def __repr__(self) -> str: - return ( - "".format( - self.error_code, - self.last_stream_id, - _bytes_representation( - self.additional_data[:20] - if self.additional_data else None), - ) - ) - - -class AlternativeServiceAvailable(Event): - """ - The AlternativeServiceAvailable event is fired when the remote peer - advertises an `RFC 7838 `_ Alternative - Service using an ALTSVC frame. - - This event always carries the origin to which the ALTSVC information - applies. That origin is either supplied by the server directly, or inferred - by h2 from the ``:authority`` pseudo-header field that was sent by - the user when initiating a given stream. - - This event also carries what RFC 7838 calls the "Alternative Service Field - Value", which is formatted like a HTTP header field and contains the - relevant alternative service information. h2 does not parse or in any - way modify that information: the user is required to do that. - - This event can only be fired on the client end of a connection. - - .. versionadded:: 2.3.0 - """ - - def __init__(self) -> None: - #: The origin to which the alternative service field value applies. - #: This field is either supplied by the server directly, or inferred by - #: h2 from the ``:authority`` pseudo-header field that was sent - #: by the user when initiating the stream on which the frame was - #: received. - self.origin: bytes | None = None - - #: The ALTSVC field value. This contains information about the HTTP - #: alternative service being advertised by the server. h2 does - #: not parse this field: it is left exactly as sent by the server. The - #: structure of the data in this field is given by `RFC 7838 Section 3 - #: `_. - self.field_value: bytes | None = None - - def __repr__(self) -> str: - return ( - "".format( - (self.origin or b"").decode("utf-8", "ignore"), - (self.field_value or b"").decode("utf-8", "ignore"), - ) - ) - - -class UnknownFrameReceived(Event): - """ - The UnknownFrameReceived event is fired when the remote peer sends a frame - that h2 does not understand. This occurs primarily when the remote - peer is employing HTTP/2 extensions that h2 doesn't know anything - about. - - RFC 7540 requires that HTTP/2 implementations ignore these frames. h2 - does so. However, this event is fired to allow implementations to perform - special processing on those frames if needed (e.g. if the implementation - is capable of handling the frame itself). - - .. versionadded:: 2.7.0 - """ - - def __init__(self) -> None: - #: The hyperframe Frame object that encapsulates the received frame. - self.frame: Frame | None = None - - def __repr__(self) -> str: - return "" - - -def _bytes_representation(data: bytes | None) -> str | None: - """ - Converts a bytestring into something that is safe to print on all Python - platforms. - - This function is relatively expensive, so it should not be called on the - mainline of the code. It's safe to use in things like object repr methods - though. - """ - if data is None: - return None - - return binascii.hexlify(data).decode("ascii") diff --git a/serverenv/lib/python3.9/site-packages/h2/exceptions.py b/serverenv/lib/python3.9/site-packages/h2/exceptions.py deleted file mode 100644 index e477679..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/exceptions.py +++ /dev/null @@ -1,194 +0,0 @@ -""" -h2/exceptions -~~~~~~~~~~~~~ - -Exceptions for the HTTP/2 module. -""" -from __future__ import annotations - -from .errors import ErrorCodes - - -class H2Error(Exception): - """ - The base class for all exceptions for the HTTP/2 module. - """ - - -class ProtocolError(H2Error): - """ - An action was attempted in violation of the HTTP/2 protocol. - """ - - #: The error code corresponds to this kind of Protocol Error. - error_code = ErrorCodes.PROTOCOL_ERROR - - -class FrameTooLargeError(ProtocolError): - """ - The frame that we tried to send or that we received was too large. - """ - - #: The error code corresponds to this kind of Protocol Error. - error_code = ErrorCodes.FRAME_SIZE_ERROR - - -class FrameDataMissingError(ProtocolError): - """ - The frame that we received is missing some data. - - .. versionadded:: 2.0.0 - """ - - #: The error code corresponds to this kind of Protocol Error. - error_code = ErrorCodes.FRAME_SIZE_ERROR - - -class TooManyStreamsError(ProtocolError): - """ - An attempt was made to open a stream that would lead to too many concurrent - streams. - """ - - - -class FlowControlError(ProtocolError): - """ - An attempted action violates flow control constraints. - """ - - #: The error code corresponds to this kind of Protocol Error. - error_code = ErrorCodes.FLOW_CONTROL_ERROR - - -class StreamIDTooLowError(ProtocolError): - """ - An attempt was made to open a stream that had an ID that is lower than the - highest ID we have seen on this connection. - """ - - def __init__(self, stream_id: int, max_stream_id: int) -> None: - #: The ID of the stream that we attempted to open. - self.stream_id = stream_id - - #: The current highest-seen stream ID. - self.max_stream_id = max_stream_id - - def __str__(self) -> str: - return f"StreamIDTooLowError: {self.stream_id} is lower than {self.max_stream_id}" - - -class NoAvailableStreamIDError(ProtocolError): - """ - There are no available stream IDs left to the connection. All stream IDs - have been exhausted. - - .. versionadded:: 2.0.0 - """ - - - -class NoSuchStreamError(ProtocolError): - """ - A stream-specific action referenced a stream that does not exist. - - .. versionchanged:: 2.0.0 - Became a subclass of :class:`ProtocolError - ` - """ - - def __init__(self, stream_id: int) -> None: - #: The stream ID corresponds to the non-existent stream. - self.stream_id = stream_id - - -class StreamClosedError(NoSuchStreamError): - """ - A more specific form of - :class:`NoSuchStreamError `. Indicates - that the stream has since been closed, and that all state relating to that - stream has been removed. - """ - - def __init__(self, stream_id: int) -> None: - #: The stream ID corresponds to the nonexistent stream. - self.stream_id = stream_id - - #: The relevant HTTP/2 error code. - self.error_code = ErrorCodes.STREAM_CLOSED - - # Any events that internal code may need to fire. Not relevant to - # external users that may receive a StreamClosedError. - self._events = [] # type: ignore - - -class InvalidSettingsValueError(ProtocolError, ValueError): - """ - An attempt was made to set an invalid Settings value. - - .. versionadded:: 2.0.0 - """ - - def __init__(self, msg: str, error_code: ErrorCodes) -> None: - super().__init__(msg) - self.error_code = error_code - - -class InvalidBodyLengthError(ProtocolError): - """ - The remote peer sent more or less data that the Content-Length header - indicated. - - .. versionadded:: 2.0.0 - """ - - def __init__(self, expected: int, actual: int) -> None: - self.expected_length = expected - self.actual_length = actual - - def __str__(self) -> str: - return f"InvalidBodyLengthError: Expected {self.expected_length} bytes, received {self.actual_length}" - - -class UnsupportedFrameError(ProtocolError): - """ - The remote peer sent a frame that is unsupported in this context. - - .. versionadded:: 2.1.0 - - .. versionchanged:: 4.0.0 - Removed deprecated KeyError parent class. - """ - - - -class RFC1122Error(H2Error): - """ - Emitted when users attempt to do something that is literally allowed by the - relevant RFC, but is sufficiently ill-defined that it's unwise to allow - users to actually do it. - - While there is some disagreement about whether or not we should be liberal - in what accept, it is a truth universally acknowledged that we should be - conservative in what emit. - - .. versionadded:: 2.4.0 - """ - - # shazow says I'm going to regret naming the exception this way. If that - # turns out to be true, TELL HIM NOTHING. - - -class DenialOfServiceError(ProtocolError): - """ - Emitted when the remote peer exhibits a behaviour that is likely to be an - attempt to perform a Denial of Service attack on the implementation. This - is a form of ProtocolError that carries a different error code, and allows - more easy detection of this kind of behaviour. - - .. versionadded:: 2.5.0 - """ - - #: The error code corresponds to this kind of - #: :class:`ProtocolError ` - error_code = ErrorCodes.ENHANCE_YOUR_CALM diff --git a/serverenv/lib/python3.9/site-packages/h2/frame_buffer.py b/serverenv/lib/python3.9/site-packages/h2/frame_buffer.py deleted file mode 100644 index 30d96e8..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/frame_buffer.py +++ /dev/null @@ -1,161 +0,0 @@ -""" -h2/frame_buffer -~~~~~~~~~~~~~~~ - -A data structure that provides a way to iterate over a byte buffer in terms of -frames. -""" -from __future__ import annotations - -from hyperframe.exceptions import InvalidDataError, InvalidFrameError -from hyperframe.frame import ContinuationFrame, Frame, HeadersFrame, PushPromiseFrame - -from .exceptions import FrameDataMissingError, FrameTooLargeError, ProtocolError - -# To avoid a DOS attack based on sending loads of continuation frames, we limit -# the maximum number we're perpared to receive. In this case, we'll set the -# limit to 64, which means the largest encoded header block we can receive by -# default is 262144 bytes long, and the largest possible *at all* is 1073741760 -# bytes long. -# -# This value seems reasonable for now, but in future we may want to evaluate -# making it configurable. -CONTINUATION_BACKLOG = 64 - - -class FrameBuffer: - """ - A buffer data structure for HTTP/2 data that allows iteraton in terms of - H2 frames. - """ - - def __init__(self, server: bool = False) -> None: - self.data = b"" - self.max_frame_size = 0 - self._preamble = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" if server else b"" - self._preamble_len = len(self._preamble) - self._headers_buffer: list[HeadersFrame | ContinuationFrame | PushPromiseFrame] = [] - - def add_data(self, data: bytes) -> None: - """ - Add more data to the frame buffer. - - :param data: A bytestring containing the byte buffer. - """ - if self._preamble_len: - data_len = len(data) - of_which_preamble = min(self._preamble_len, data_len) - - if self._preamble[:of_which_preamble] != data[:of_which_preamble]: - msg = "Invalid HTTP/2 preamble." - raise ProtocolError(msg) - - data = data[of_which_preamble:] - self._preamble_len -= of_which_preamble - self._preamble = self._preamble[of_which_preamble:] - - self.data += data - - def _validate_frame_length(self, length: int) -> None: - """ - Confirm that the frame is an appropriate length. - """ - if length > self.max_frame_size: - msg = f"Received overlong frame: length {length}, max {self.max_frame_size}" - raise FrameTooLargeError(msg) - - def _update_header_buffer(self, f: Frame | None) -> Frame | None: - """ - Updates the internal header buffer. Returns a frame that should replace - the current one. May throw exceptions if this frame is invalid. - """ - # Check if we're in the middle of a headers block. If we are, this - # frame *must* be a CONTINUATION frame with the same stream ID as the - # leading HEADERS or PUSH_PROMISE frame. Anything else is a - # ProtocolError. If the frame *is* valid, append it to the header - # buffer. - if self._headers_buffer: - stream_id = self._headers_buffer[0].stream_id - valid_frame = ( - f is not None and - isinstance(f, ContinuationFrame) and - f.stream_id == stream_id - ) - if not valid_frame: - msg = "Invalid frame during header block." - raise ProtocolError(msg) - assert isinstance(f, ContinuationFrame) - - # Append the frame to the buffer. - self._headers_buffer.append(f) - if len(self._headers_buffer) > CONTINUATION_BACKLOG: - msg = "Too many continuation frames received." - raise ProtocolError(msg) - - # If this is the end of the header block, then we want to build a - # mutant HEADERS frame that's massive. Use the original one we got, - # then set END_HEADERS and set its data appopriately. If it's not - # the end of the block, lose the current frame: we can't yield it. - if "END_HEADERS" in f.flags: - f = self._headers_buffer[0] - f.flags.add("END_HEADERS") - f.data = b"".join(x.data for x in self._headers_buffer) - self._headers_buffer = [] - else: - f = None - elif (isinstance(f, (HeadersFrame, PushPromiseFrame)) and - "END_HEADERS" not in f.flags): - # This is the start of a headers block! Save the frame off and then - # act like we didn't receive one. - self._headers_buffer.append(f) - f = None - - return f - - # The methods below support the iterator protocol. - def __iter__(self) -> FrameBuffer: - return self - - def __next__(self) -> Frame: - # First, check that we have enough data to successfully parse the - # next frame header. If not, bail. Otherwise, parse it. - if len(self.data) < 9: - raise StopIteration - - try: - f, length = Frame.parse_frame_header(memoryview(self.data[:9])) - except (InvalidDataError, InvalidFrameError) as err: # pragma: no cover - msg = f"Received frame with invalid header: {err!s}" - raise ProtocolError(msg) from err - - # Next, check that we have enough length to parse the frame body. If - # not, bail, leaving the frame header data in the buffer for next time. - if len(self.data) < length + 9: - raise StopIteration - - # Confirm the frame has an appropriate length. - self._validate_frame_length(length) - - # Try to parse the frame body - try: - f.parse_body(memoryview(self.data[9:9+length])) - except InvalidDataError as err: - msg = "Received frame with non-compliant data" - raise ProtocolError(msg) from err - except InvalidFrameError as err: - msg = "Frame data missing or invalid" - raise FrameDataMissingError(msg) from err - - # At this point, as we know we'll use or discard the entire frame, we - # can update the data. - self.data = self.data[9+length:] - - # Pass the frame through the header buffer. - new_frame = self._update_header_buffer(f) - - # If we got a frame we didn't understand or shouldn't yield, rather - # than return None it'd be better if we just tried to get the next - # frame in the sequence instead. Recurse back into ourselves to do - # that. This is safe because the amount of work we have to do here is - # strictly bounded by the length of the buffer. - return new_frame if new_frame is not None else self.__next__() diff --git a/serverenv/lib/python3.9/site-packages/h2/py.typed b/serverenv/lib/python3.9/site-packages/h2/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/h2/settings.py b/serverenv/lib/python3.9/site-packages/h2/settings.py deleted file mode 100644 index c1be953..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/settings.py +++ /dev/null @@ -1,331 +0,0 @@ -""" -h2/settings -~~~~~~~~~~~ - -This module contains a HTTP/2 settings object. This object provides a simple -API for manipulating HTTP/2 settings, keeping track of both the current active -state of the settings and the unacknowledged future values of the settings. -""" -from __future__ import annotations - -import collections -import enum -from collections.abc import Iterator, MutableMapping -from typing import Union - -from hyperframe.frame import SettingsFrame - -from .errors import ErrorCodes -from .exceptions import InvalidSettingsValueError - - -class SettingCodes(enum.IntEnum): - """ - All known HTTP/2 setting codes. - - .. versionadded:: 2.6.0 - """ - - #: Allows the sender to inform the remote endpoint of the maximum size of - #: the header compression table used to decode header blocks, in octets. - HEADER_TABLE_SIZE = SettingsFrame.HEADER_TABLE_SIZE - - #: This setting can be used to disable server push. To disable server push - #: on a client, set this to 0. - ENABLE_PUSH = SettingsFrame.ENABLE_PUSH - - #: Indicates the maximum number of concurrent streams that the sender will - #: allow. - MAX_CONCURRENT_STREAMS = SettingsFrame.MAX_CONCURRENT_STREAMS - - #: Indicates the sender's initial window size (in octets) for stream-level - #: flow control. - INITIAL_WINDOW_SIZE = SettingsFrame.INITIAL_WINDOW_SIZE - - #: Indicates the size of the largest frame payload that the sender is - #: willing to receive, in octets. - MAX_FRAME_SIZE = SettingsFrame.MAX_FRAME_SIZE - - #: This advisory setting informs a peer of the maximum size of header list - #: that the sender is prepared to accept, in octets. The value is based on - #: the uncompressed size of header fields, including the length of the name - #: and value in octets plus an overhead of 32 octets for each header field. - MAX_HEADER_LIST_SIZE = SettingsFrame.MAX_HEADER_LIST_SIZE - - #: This setting can be used to enable the connect protocol. To enable on a - #: client set this to 1. - ENABLE_CONNECT_PROTOCOL = SettingsFrame.ENABLE_CONNECT_PROTOCOL - - -def _setting_code_from_int(code: int) -> SettingCodes | int: - """ - Given an integer setting code, returns either one of :class:`SettingCodes - ` or, if not present in the known set of codes, - returns the integer directly. - """ - try: - return SettingCodes(code) - except ValueError: - return code - - -class ChangedSetting: - - def __init__(self, setting: SettingCodes | int, original_value: int | None, new_value: int) -> None: - #: The setting code given. Either one of :class:`SettingCodes - #: ` or ``int`` - #: - #: .. versionchanged:: 2.6.0 - self.setting = setting - - #: The original value before being changed. - self.original_value = original_value - - #: The new value after being changed. - self.new_value = new_value - - def __repr__(self) -> str: - return ( - f"ChangedSetting(setting={self.setting!s}, original_value={self.original_value}, new_value={self.new_value})" - ) - - -class Settings(MutableMapping[Union[SettingCodes, int], int]): - """ - An object that encapsulates HTTP/2 settings state. - - HTTP/2 Settings are a complex beast. Each party, remote and local, has its - own settings and a view of the other party's settings. When a settings - frame is emitted by a peer it cannot assume that the new settings values - are in place until the remote peer acknowledges the setting. In principle, - multiple settings changes can be "in flight" at the same time, all with - different values. - - This object encapsulates this mess. It provides a dict-like interface to - settings, which return the *current* values of the settings in question. - Additionally, it keeps track of the stack of proposed values: each time an - acknowledgement is sent/received, it updates the current values with the - stack of proposed values. On top of all that, it validates the values to - make sure they're allowed, and raises :class:`InvalidSettingsValueError - ` if they are not. - - Finally, this object understands what the default values of the HTTP/2 - settings are, and sets those defaults appropriately. - - .. versionchanged:: 2.2.0 - Added the ``initial_values`` parameter. - - .. versionchanged:: 2.5.0 - Added the ``max_header_list_size`` property. - - :param client: (optional) Whether these settings should be defaulted for a - client implementation or a server implementation. Defaults to ``True``. - :type client: ``bool`` - :param initial_values: (optional) Any initial values the user would like - set, rather than RFC 7540's defaults. - :type initial_vales: ``MutableMapping`` - """ - - def __init__(self, client: bool = True, initial_values: dict[SettingCodes, int] | None = None) -> None: - # Backing object for the settings. This is a dictionary of - # (setting: [list of values]), where the first value in the list is the - # current value of the setting. Strictly this doesn't use lists but - # instead uses collections.deque to avoid repeated memory allocations. - # - # This contains the default values for HTTP/2. - self._settings: dict[SettingCodes | int, collections.deque[int]] = { - SettingCodes.HEADER_TABLE_SIZE: collections.deque([4096]), - SettingCodes.ENABLE_PUSH: collections.deque([int(client)]), - SettingCodes.INITIAL_WINDOW_SIZE: collections.deque([65535]), - SettingCodes.MAX_FRAME_SIZE: collections.deque([16384]), - SettingCodes.ENABLE_CONNECT_PROTOCOL: collections.deque([0]), - } - if initial_values is not None: - for key, value in initial_values.items(): - invalid = _validate_setting(key, value) - if invalid: - msg = f"Setting {key} has invalid value {value}" - raise InvalidSettingsValueError( - msg, - error_code=invalid, - ) - self._settings[key] = collections.deque([value]) - - def acknowledge(self) -> dict[SettingCodes | int, ChangedSetting]: - """ - The settings have been acknowledged, either by the user (remote - settings) or by the remote peer (local settings). - - :returns: A dict of {setting: ChangedSetting} that were applied. - """ - changed_settings: dict[SettingCodes | int, ChangedSetting] = {} - - # If there is more than one setting in the list, we have a setting - # value outstanding. Update them. - for k, v in self._settings.items(): - if len(v) > 1: - old_setting = v.popleft() - new_setting = v[0] - changed_settings[k] = ChangedSetting( - k, old_setting, new_setting, - ) - - return changed_settings - - # Provide easy-access to well known settings. - @property - def header_table_size(self) -> int: - """ - The current value of the :data:`HEADER_TABLE_SIZE - ` setting. - """ - return self[SettingCodes.HEADER_TABLE_SIZE] - - @header_table_size.setter - def header_table_size(self, value: int) -> None: - self[SettingCodes.HEADER_TABLE_SIZE] = value - - @property - def enable_push(self) -> int: - """ - The current value of the :data:`ENABLE_PUSH - ` setting. - """ - return self[SettingCodes.ENABLE_PUSH] - - @enable_push.setter - def enable_push(self, value: int) -> None: - self[SettingCodes.ENABLE_PUSH] = value - - @property - def initial_window_size(self) -> int: - """ - The current value of the :data:`INITIAL_WINDOW_SIZE - ` setting. - """ - return self[SettingCodes.INITIAL_WINDOW_SIZE] - - @initial_window_size.setter - def initial_window_size(self, value: int) -> None: - self[SettingCodes.INITIAL_WINDOW_SIZE] = value - - @property - def max_frame_size(self) -> int: - """ - The current value of the :data:`MAX_FRAME_SIZE - ` setting. - """ - return self[SettingCodes.MAX_FRAME_SIZE] - - @max_frame_size.setter - def max_frame_size(self, value: int) -> None: - self[SettingCodes.MAX_FRAME_SIZE] = value - - @property - def max_concurrent_streams(self) -> int: - """ - The current value of the :data:`MAX_CONCURRENT_STREAMS - ` setting. - """ - return self.get(SettingCodes.MAX_CONCURRENT_STREAMS, 2**32+1) - - @max_concurrent_streams.setter - def max_concurrent_streams(self, value: int) -> None: - self[SettingCodes.MAX_CONCURRENT_STREAMS] = value - - @property - def max_header_list_size(self) -> int | None: - """ - The current value of the :data:`MAX_HEADER_LIST_SIZE - ` setting. If not set, - returns ``None``, which means unlimited. - - .. versionadded:: 2.5.0 - """ - return self.get(SettingCodes.MAX_HEADER_LIST_SIZE, None) - - @max_header_list_size.setter - def max_header_list_size(self, value: int) -> None: - self[SettingCodes.MAX_HEADER_LIST_SIZE] = value - - @property - def enable_connect_protocol(self) -> int: - """ - The current value of the :data:`ENABLE_CONNECT_PROTOCOL - ` setting. - """ - return self[SettingCodes.ENABLE_CONNECT_PROTOCOL] - - @enable_connect_protocol.setter - def enable_connect_protocol(self, value: int) -> None: - self[SettingCodes.ENABLE_CONNECT_PROTOCOL] = value - - # Implement the MutableMapping API. - def __getitem__(self, key: SettingCodes | int) -> int: - val = self._settings[key][0] - - # Things that were created when a setting was received should stay - # KeyError'd. - if val is None: - raise KeyError - - return val - - def __setitem__(self, key: SettingCodes | int, value: int) -> None: - invalid = _validate_setting(key, value) - if invalid: - msg = f"Setting {key} has invalid value {value}" - raise InvalidSettingsValueError( - msg, - error_code=invalid, - ) - - try: - items = self._settings[key] - except KeyError: - items = collections.deque([None]) # type: ignore - self._settings[key] = items - - items.append(value) - - def __delitem__(self, key: SettingCodes | int) -> None: - del self._settings[key] - - def __iter__(self) -> Iterator[SettingCodes | int]: - return self._settings.__iter__() - - def __len__(self) -> int: - return len(self._settings) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Settings): - return self._settings == other._settings - return NotImplemented - - def __ne__(self, other: object) -> bool: - if isinstance(other, Settings): - return not self == other - return NotImplemented - - -def _validate_setting(setting: SettingCodes | int, value: int) -> ErrorCodes: - """ - Confirms that a specific setting has a well-formed value. If the setting is - invalid, returns an error code. Otherwise, returns 0 (NO_ERROR). - """ - if setting == SettingCodes.ENABLE_PUSH: - if value not in (0, 1): - return ErrorCodes.PROTOCOL_ERROR - elif setting == SettingCodes.INITIAL_WINDOW_SIZE: - if not 0 <= value <= 2147483647: # 2^31 - 1 - return ErrorCodes.FLOW_CONTROL_ERROR - elif setting == SettingCodes.MAX_FRAME_SIZE: - if not 16384 <= value <= 16777215: # 2^14 and 2^24 - 1 - return ErrorCodes.PROTOCOL_ERROR - elif setting == SettingCodes.MAX_HEADER_LIST_SIZE: - if value < 0: - return ErrorCodes.PROTOCOL_ERROR - elif setting == SettingCodes.ENABLE_CONNECT_PROTOCOL and value not in (0, 1): - return ErrorCodes.PROTOCOL_ERROR - - return ErrorCodes.NO_ERROR diff --git a/serverenv/lib/python3.9/site-packages/h2/stream.py b/serverenv/lib/python3.9/site-packages/h2/stream.py deleted file mode 100644 index 7d4a12e..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/stream.py +++ /dev/null @@ -1,1417 +0,0 @@ -""" -h2/stream -~~~~~~~~~ - -An implementation of a HTTP/2 stream. -""" -from __future__ import annotations - -from enum import Enum, IntEnum -from typing import TYPE_CHECKING, Any - -from hpack import HeaderTuple -from hyperframe.frame import AltSvcFrame, ContinuationFrame, DataFrame, Frame, HeadersFrame, PushPromiseFrame, RstStreamFrame, WindowUpdateFrame - -from .errors import ErrorCodes, _error_code_from_int -from .events import ( - AlternativeServiceAvailable, - DataReceived, - Event, - InformationalResponseReceived, - PushedStreamReceived, - RequestReceived, - ResponseReceived, - StreamEnded, - StreamReset, - TrailersReceived, - WindowUpdated, - _PushedRequestSent, - _RequestSent, - _ResponseSent, - _TrailersSent, -) -from .exceptions import FlowControlError, InvalidBodyLengthError, ProtocolError, StreamClosedError -from .utilities import ( - HeaderValidationFlags, - authority_from_headers, - extract_method_header, - guard_increment_window, - is_informational_response, - normalize_inbound_headers, - normalize_outbound_headers, - utf8_encode_headers, - validate_headers, - validate_outbound_headers, -) -from .windows import WindowManager - -if TYPE_CHECKING: # pragma: no cover - from collections.abc import Generator, Iterable - - from hpack.hpack import Encoder - from hpack.struct import Header, HeaderWeaklyTyped - - from .config import H2Configuration - - -class StreamState(IntEnum): - IDLE = 0 - RESERVED_REMOTE = 1 - RESERVED_LOCAL = 2 - OPEN = 3 - HALF_CLOSED_REMOTE = 4 - HALF_CLOSED_LOCAL = 5 - CLOSED = 6 - - -class StreamInputs(Enum): - SEND_HEADERS = 0 - SEND_PUSH_PROMISE = 1 - SEND_RST_STREAM = 2 - SEND_DATA = 3 - SEND_WINDOW_UPDATE = 4 - SEND_END_STREAM = 5 - RECV_HEADERS = 6 - RECV_PUSH_PROMISE = 7 - RECV_RST_STREAM = 8 - RECV_DATA = 9 - RECV_WINDOW_UPDATE = 10 - RECV_END_STREAM = 11 - RECV_CONTINUATION = 12 # Added in 2.0.0 - SEND_INFORMATIONAL_HEADERS = 13 # Added in 2.2.0 - RECV_INFORMATIONAL_HEADERS = 14 # Added in 2.2.0 - SEND_ALTERNATIVE_SERVICE = 15 # Added in 2.3.0 - RECV_ALTERNATIVE_SERVICE = 16 # Added in 2.3.0 - UPGRADE_CLIENT = 17 # Added 2.3.0 - UPGRADE_SERVER = 18 # Added 2.3.0 - - -class StreamClosedBy(Enum): - SEND_END_STREAM = 0 - RECV_END_STREAM = 1 - SEND_RST_STREAM = 2 - RECV_RST_STREAM = 3 - - -# This array is initialized once, and is indexed by the stream states above. -# It indicates whether a stream in the given state is open. The reason we do -# this is that we potentially check whether a stream in a given state is open -# quite frequently: given that we check so often, we should do so in the -# fastest and most performant way possible. -STREAM_OPEN = [False for _ in range(len(StreamState))] -STREAM_OPEN[StreamState.OPEN] = True -STREAM_OPEN[StreamState.HALF_CLOSED_LOCAL] = True -STREAM_OPEN[StreamState.HALF_CLOSED_REMOTE] = True - - -class H2StreamStateMachine: - """ - A single HTTP/2 stream state machine. - - This stream object implements basically the state machine described in - RFC 7540 section 5.1. - - :param stream_id: The stream ID of this stream. This is stored primarily - for logging purposes. - """ - - def __init__(self, stream_id: int) -> None: - self.state = StreamState.IDLE - self.stream_id = stream_id - - #: Whether this peer is the client side of this stream. - self.client: bool | None = None - - # Whether trailers have been sent/received on this stream or not. - self.headers_sent: bool | None = None - self.trailers_sent: bool | None = None - self.headers_received: bool | None = None - self.trailers_received: bool | None = None - - # How the stream was closed. One of StreamClosedBy. - self.stream_closed_by: StreamClosedBy | None = None - - def process_input(self, input_: StreamInputs) -> Any: - """ - Process a specific input in the state machine. - """ - if not isinstance(input_, StreamInputs): - msg = "Input must be an instance of StreamInputs" - raise ValueError(msg) # noqa: TRY004 - - try: - func, target_state = _transitions[(self.state, input_)] - except KeyError as err: - old_state = self.state - self.state = StreamState.CLOSED - msg = f"Invalid input {input_} in state {old_state}" - raise ProtocolError(msg) from err - else: - previous_state = self.state - self.state = target_state - if func is not None: - try: - return func(self, previous_state) - except ProtocolError: - self.state = StreamState.CLOSED - raise - except AssertionError as err: # pragma: no cover - self.state = StreamState.CLOSED - raise ProtocolError(err) from err - - return [] - - def request_sent(self, previous_state: StreamState) -> list[Event]: - """ - Fires when a request is sent. - """ - self.client = True - self.headers_sent = True - event = _RequestSent() - - return [event] - - def response_sent(self, previous_state: StreamState) -> list[Event]: - """ - Fires when something that should be a response is sent. This 'response' - may actually be trailers. - """ - if not self.headers_sent: - if self.client is True or self.client is None: - msg = "Client cannot send responses." - raise ProtocolError(msg) - self.headers_sent = True - return [_ResponseSent()] - assert not self.trailers_sent - self.trailers_sent = True - return [_TrailersSent()] - - def request_received(self, previous_state: StreamState) -> list[Event]: - """ - Fires when a request is received. - """ - assert not self.headers_received - assert not self.trailers_received - - self.client = False - self.headers_received = True - event = RequestReceived() - event.stream_id = self.stream_id - return [event] - - def response_received(self, previous_state: StreamState) -> list[Event]: - """ - Fires when a response is received. Also disambiguates between responses - and trailers. - """ - event: ResponseReceived | TrailersReceived - if not self.headers_received: - assert self.client is True - self.headers_received = True - event = ResponseReceived() - else: - assert not self.trailers_received - self.trailers_received = True - event = TrailersReceived() - - event.stream_id = self.stream_id - return [event] - - def data_received(self, previous_state: StreamState) -> list[Event]: - """ - Fires when data is received. - """ - if not self.headers_received: - msg = "cannot receive data before headers" - raise ProtocolError(msg) - event = DataReceived() - event.stream_id = self.stream_id - return [event] - - def window_updated(self, previous_state: StreamState) -> list[Event]: - """ - Fires when a window update frame is received. - """ - event = WindowUpdated() - event.stream_id = self.stream_id - return [event] - - def stream_half_closed(self, previous_state: StreamState) -> list[Event]: - """ - Fires when an END_STREAM flag is received in the OPEN state, - transitioning this stream to a HALF_CLOSED_REMOTE state. - """ - event = StreamEnded() - event.stream_id = self.stream_id - return [event] - - def stream_ended(self, previous_state: StreamState) -> list[Event]: - """ - Fires when a stream is cleanly ended. - """ - self.stream_closed_by = StreamClosedBy.RECV_END_STREAM - event = StreamEnded() - event.stream_id = self.stream_id - return [event] - - def stream_reset(self, previous_state: StreamState) -> list[Event]: - """ - Fired when a stream is forcefully reset. - """ - self.stream_closed_by = StreamClosedBy.RECV_RST_STREAM - event = StreamReset() - event.stream_id = self.stream_id - return [event] - - def send_new_pushed_stream(self, previous_state: StreamState) -> list[Event]: - """ - Fires on the newly pushed stream, when pushed by the local peer. - - No event here, but definitionally this peer must be a server. - """ - assert self.client is None - self.client = False - self.headers_received = True - return [] - - def recv_new_pushed_stream(self, previous_state: StreamState) -> list[Event]: - """ - Fires on the newly pushed stream, when pushed by the remote peer. - - No event here, but definitionally this peer must be a client. - """ - assert self.client is None - self.client = True - self.headers_sent = True - return [] - - def send_push_promise(self, previous_state: StreamState) -> list[Event]: - """ - Fires on the already-existing stream when a PUSH_PROMISE frame is sent. - We may only send PUSH_PROMISE frames if we're a server. - """ - if self.client is True: - msg = "Cannot push streams from client peers." - raise ProtocolError(msg) - - event = _PushedRequestSent() - return [event] - - def recv_push_promise(self, previous_state: StreamState) -> list[Event]: - """ - Fires on the already-existing stream when a PUSH_PROMISE frame is - received. We may only receive PUSH_PROMISE frames if we're a client. - - Fires a PushedStreamReceived event. - """ - if not self.client: - if self.client is None: # pragma: no cover - msg = "Idle streams cannot receive pushes" - else: # pragma: no cover - msg = "Cannot receive pushed streams as a server" - raise ProtocolError(msg) - - event = PushedStreamReceived() - event.parent_stream_id = self.stream_id - return [event] - - def send_end_stream(self, previous_state: StreamState) -> None: - """ - Called when an attempt is made to send END_STREAM in the - HALF_CLOSED_REMOTE state. - """ - self.stream_closed_by = StreamClosedBy.SEND_END_STREAM - - def send_reset_stream(self, previous_state: StreamState) -> None: - """ - Called when an attempt is made to send RST_STREAM in a non-closed - stream state. - """ - self.stream_closed_by = StreamClosedBy.SEND_RST_STREAM - - def reset_stream_on_error(self, previous_state: StreamState) -> None: - """ - Called when we need to forcefully emit another RST_STREAM frame on - behalf of the state machine. - - If this is the first time we've done this, we should also hang an event - off the StreamClosedError so that the user can be informed. We know - it's the first time we've done this if the stream is currently in a - state other than CLOSED. - """ - self.stream_closed_by = StreamClosedBy.SEND_RST_STREAM - - error = StreamClosedError(self.stream_id) - - event = StreamReset() - event.stream_id = self.stream_id - event.error_code = ErrorCodes.STREAM_CLOSED - event.remote_reset = False - error._events = [event] - raise error - - def recv_on_closed_stream(self, previous_state: StreamState) -> None: - """ - Called when an unexpected frame is received on an already-closed - stream. - - An endpoint that receives an unexpected frame should treat it as - a stream error or connection error with type STREAM_CLOSED, depending - on the specific frame. The error handling is done at a higher level: - this just raises the appropriate error. - """ - raise StreamClosedError(self.stream_id) - - def send_on_closed_stream(self, previous_state: StreamState) -> None: - """ - Called when an attempt is made to send data on an already-closed - stream. - - This essentially overrides the standard logic by throwing a - more-specific error: StreamClosedError. This is a ProtocolError, so it - matches the standard API of the state machine, but provides more detail - to the user. - """ - raise StreamClosedError(self.stream_id) - - def recv_push_on_closed_stream(self, previous_state: StreamState) -> None: - """ - Called when a PUSH_PROMISE frame is received on a full stop - stream. - - If the stream was closed by us sending a RST_STREAM frame, then we - presume that the PUSH_PROMISE was in flight when we reset the parent - stream. Rathen than accept the new stream, we just reset it. - Otherwise, we should call this a PROTOCOL_ERROR: pushing a stream on a - naturally closed stream is a real problem because it creates a brand - new stream that the remote peer now believes exists. - """ - assert self.stream_closed_by is not None - - if self.stream_closed_by == StreamClosedBy.SEND_RST_STREAM: - raise StreamClosedError(self.stream_id) - msg = "Attempted to push on closed stream." - raise ProtocolError(msg) - - def send_push_on_closed_stream(self, previous_state: StreamState) -> None: - """ - Called when an attempt is made to push on an already-closed stream. - - This essentially overrides the standard logic by providing a more - useful error message. It's necessary because simply indicating that the - stream is closed is not enough: there is now a new stream that is not - allowed to be there. The only recourse is to tear the whole connection - down. - """ - msg = "Attempted to push on closed stream." - raise ProtocolError(msg) - - def send_informational_response(self, previous_state: StreamState) -> list[Event]: - """ - Called when an informational header block is sent (that is, a block - where the :status header has a 1XX value). - - Only enforces that these are sent *before* final headers are sent. - """ - if self.headers_sent: - msg = "Information response after final response" - raise ProtocolError(msg) - - event = _ResponseSent() - return [event] - - def recv_informational_response(self, previous_state: StreamState) -> list[Event]: - """ - Called when an informational header block is received (that is, a block - where the :status header has a 1XX value). - """ - if self.headers_received: - msg = "Informational response after final response" - raise ProtocolError(msg) - - event = InformationalResponseReceived() - event.stream_id = self.stream_id - return [event] - - def recv_alt_svc(self, previous_state: StreamState) -> list[Event]: - """ - Called when receiving an ALTSVC frame. - - RFC 7838 allows us to receive ALTSVC frames at any stream state, which - is really absurdly overzealous. For that reason, we want to limit the - states in which we can actually receive it. It's really only sensible - to receive it after we've sent our own headers and before the server - has sent its header block: the server can't guarantee that we have any - state around after it completes its header block, and the server - doesn't know what origin we're talking about before we've sent ours. - - For that reason, this function applies a few extra checks on both state - and some of the little state variables we keep around. If those suggest - an unreasonable situation for the ALTSVC frame to have been sent in, - we quietly ignore it (as RFC 7838 suggests). - - This function is also *not* always called by the state machine. In some - states (IDLE, RESERVED_LOCAL, CLOSED) we don't bother to call it, - because we know the frame cannot be valid in that state (IDLE because - the server cannot know what origin the stream applies to, CLOSED - because the server cannot assume we still have state around, - RESERVED_LOCAL because by definition if we're in the RESERVED_LOCAL - state then *we* are the server). - """ - # Servers can't receive ALTSVC frames, but RFC 7838 tells us to ignore - # them. - if self.client is False: - return [] - - # If we've received the response headers from the server they can't - # guarantee we still have any state around. Other implementations - # (like nghttp2) ignore ALTSVC in this state, so we will too. - if self.headers_received: - return [] - - # Otherwise, this is a sensible enough frame to have received. Return - # the event and let it get populated. - return [AlternativeServiceAvailable()] - - def send_alt_svc(self, previous_state: StreamState) -> None: - """ - Called when sending an ALTSVC frame on this stream. - - For consistency with the restrictions we apply on receiving ALTSVC - frames in ``recv_alt_svc``, we want to restrict when users can send - ALTSVC frames to the situations when we ourselves would accept them. - - That means: when we are a server, when we have received the request - headers, and when we have not yet sent our own response headers. - """ - # We should not send ALTSVC after we've sent response headers, as the - # client may have disposed of its state. - if self.headers_sent: - msg = "Cannot send ALTSVC after sending response headers." - raise ProtocolError(msg) - - - -# STATE MACHINE -# -# The stream state machine is defined here to avoid the need to allocate it -# repeatedly for each stream. It cannot be defined in the stream class because -# it needs to be able to reference the callbacks defined on the class, but -# because Python's scoping rules are weird the class object is not actually in -# scope during the body of the class object. -# -# For the sake of clarity, we reproduce the RFC 7540 state machine here: -# -# +--------+ -# send PP | | recv PP -# ,--------| idle |--------. -# / | | \ -# v +--------+ v -# +----------+ | +----------+ -# | | | send H / | | -# ,------| reserved | | recv H | reserved |------. -# | | (local) | | | (remote) | | -# | +----------+ v +----------+ | -# | | +--------+ | | -# | | recv ES | | send ES | | -# | send H | ,-------| open |-------. | recv H | -# | | / | | \ | | -# | v v +--------+ v v | -# | +----------+ | +----------+ | -# | | half | | | half | | -# | | closed | | send R / | closed | | -# | | (remote) | | recv R | (local) | | -# | +----------+ | +----------+ | -# | | | | | -# | | send ES / | recv ES / | | -# | | send R / v send R / | | -# | | recv R +--------+ recv R | | -# | send R / `----------->| |<-----------' send R / | -# | recv R | closed | recv R | -# `----------------------->| |<----------------------' -# +--------+ -# -# send: endpoint sends this frame -# recv: endpoint receives this frame -# -# H: HEADERS frame (with implied CONTINUATIONs) -# PP: PUSH_PROMISE frame (with implied CONTINUATIONs) -# ES: END_STREAM flag -# R: RST_STREAM frame -# -# For the purposes of this state machine we treat HEADERS and their -# associated CONTINUATION frames as a single jumbo frame. The protocol -# allows/requires this by preventing other frames from being interleved in -# between HEADERS/CONTINUATION frames. However, if a CONTINUATION frame is -# received without a prior HEADERS frame, it *will* be passed to this state -# machine. The state machine should always reject that frame, either as an -# invalid transition or because the stream is closed. -# -# There is a confusing relationship around PUSH_PROMISE frames. The state -# machine above considers them to be frames belonging to the new stream, -# which is *somewhat* true. However, they are sent with the stream ID of -# their related stream, and are only sendable in some cases. -# For this reason, our state machine implementation below allows for -# PUSH_PROMISE frames both in the IDLE state (as in the diagram), but also -# in the OPEN, HALF_CLOSED_LOCAL, and HALF_CLOSED_REMOTE states. -# Essentially, for h2, PUSH_PROMISE frames are effectively sent on -# two streams. -# -# The _transitions dictionary contains a mapping of tuples of -# (state, input) to tuples of (side_effect_function, end_state). This -# map contains all allowed transitions: anything not in this map is -# invalid and immediately causes a transition to ``closed``. -_transitions = { - # State: idle - (StreamState.IDLE, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.request_sent, StreamState.OPEN), - (StreamState.IDLE, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.request_received, StreamState.OPEN), - (StreamState.IDLE, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.IDLE, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_new_pushed_stream, - StreamState.RESERVED_LOCAL), - (StreamState.IDLE, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_new_pushed_stream, - StreamState.RESERVED_REMOTE), - (StreamState.IDLE, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (None, StreamState.IDLE), - (StreamState.IDLE, StreamInputs.UPGRADE_CLIENT): - (H2StreamStateMachine.request_sent, StreamState.HALF_CLOSED_LOCAL), - (StreamState.IDLE, StreamInputs.UPGRADE_SERVER): - (H2StreamStateMachine.request_received, - StreamState.HALF_CLOSED_REMOTE), - - # State: reserved local - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.response_sent, StreamState.HALF_CLOSED_REMOTE), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.RESERVED_LOCAL), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.RESERVED_LOCAL), - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.RESERVED_LOCAL), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (None, StreamState.RESERVED_LOCAL), - - # State: reserved remote - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.response_received, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.RESERVED_REMOTE, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.RESERVED_REMOTE), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.RESERVED_REMOTE), - (StreamState.RESERVED_REMOTE, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.RESERVED_REMOTE), - - # State: open - (StreamState.OPEN, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.response_sent, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.response_received, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_DATA): - (None, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_DATA): - (H2StreamStateMachine.data_received, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_END_STREAM): - (None, StreamState.HALF_CLOSED_LOCAL), - (StreamState.OPEN, StreamInputs.RECV_END_STREAM): - (H2StreamStateMachine.stream_half_closed, - StreamState.HALF_CLOSED_REMOTE), - (StreamState.OPEN, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.OPEN, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.OPEN, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_push_promise, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_push_promise, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.send_informational_response, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.recv_informational_response, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.OPEN), - - # State: half-closed remote - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.response_sent, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_DATA): - (None, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_END_STREAM): - (H2StreamStateMachine.send_end_stream, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_push_promise, - StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.send_informational_response, - StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.HALF_CLOSED_REMOTE), - - # State: half-closed local - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.response_received, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_DATA): - (H2StreamStateMachine.data_received, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_END_STREAM): - (H2StreamStateMachine.stream_ended, StreamState.CLOSED), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_push_promise, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.recv_informational_response, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.HALF_CLOSED_LOCAL), - - # State: closed - (StreamState.CLOSED, StreamInputs.RECV_END_STREAM): - (None, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (None, StreamState.CLOSED), - - # RFC 7540 Section 5.1 defines how the end point should react when - # receiving a frame on a closed stream with the following statements: - # - # > An endpoint that receives any frame other than PRIORITY after receiving - # > a RST_STREAM MUST treat that as a stream error of type STREAM_CLOSED. - # > An endpoint that receives any frames after receiving a frame with the - # > END_STREAM flag set MUST treat that as a connection error of type - # > STREAM_CLOSED. - (StreamState.CLOSED, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.recv_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.RECV_DATA): - (H2StreamStateMachine.recv_on_closed_stream, StreamState.CLOSED), - - # > WINDOW_UPDATE or RST_STREAM frames can be received in this state - # > for a short period after a DATA or HEADERS frame containing a - # > END_STREAM flag is sent, as instructed in RFC 7540 Section 5.1. But we - # > don't have access to a clock so we just always allow it. - (StreamState.CLOSED, StreamInputs.RECV_WINDOW_UPDATE): - (None, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.RECV_RST_STREAM): - (None, StreamState.CLOSED), - - # > A receiver MUST treat the receipt of a PUSH_PROMISE on a stream that is - # > neither "open" nor "half-closed (local)" as a connection error of type - # > PROTOCOL_ERROR. - (StreamState.CLOSED, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_push_on_closed_stream, StreamState.CLOSED), - - # Also, users should be forbidden from sending on closed streams. - (StreamState.CLOSED, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_push_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_DATA): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_WINDOW_UPDATE): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_END_STREAM): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), -} - - -class H2Stream: - """ - A low-level HTTP/2 stream object. This handles building and receiving - frames and maintains per-stream state. - - This wraps a HTTP/2 Stream state machine implementation, ensuring that - frames can only be sent/received when the stream is in a valid state. - Attempts to create frames that cannot be sent will raise a - ``ProtocolError``. - """ - - def __init__(self, - stream_id: int, - config: H2Configuration, - inbound_window_size: int, - outbound_window_size: int) -> None: - self.state_machine = H2StreamStateMachine(stream_id) - self.stream_id = stream_id - self.max_outbound_frame_size: int | None = None - self.request_method: bytes | None = None - - # The current value of the outbound stream flow control window - self.outbound_flow_control_window = outbound_window_size - - # The flow control manager. - self._inbound_window_manager = WindowManager(inbound_window_size) - - # The expected content length, if any. - self._expected_content_length: int | None = None - - # The actual received content length. Always tracked. - self._actual_content_length = 0 - - # The authority we believe this stream belongs to. - self._authority: bytes | None = None - - # The configuration for this stream. - self.config = config - - def __repr__(self) -> str: - return f"<{type(self).__name__} id:{self.stream_id} state:{self.state_machine.state!r}>" - - @property - def inbound_flow_control_window(self) -> int: - """ - The size of the inbound flow control window for the stream. This is - rarely publicly useful: instead, use :meth:`remote_flow_control_window - `. This shortcut is - largely present to provide a shortcut to this data. - """ - return self._inbound_window_manager.current_window_size - - @property - def open(self) -> bool: - """ - Whether the stream is 'open' in any sense: that is, whether it counts - against the number of concurrent streams. - """ - # RFC 7540 Section 5.1.2 defines 'open' for this purpose to mean either - # the OPEN state or either of the HALF_CLOSED states. Perplexingly, - # this excludes the reserved states. - # For more detail on why we're doing this in this slightly weird way, - # see the comment on ``STREAM_OPEN`` at the top of the file. - return STREAM_OPEN[self.state_machine.state] - - @property - def closed(self) -> bool: - """ - Whether the stream is closed. - """ - return self.state_machine.state == StreamState.CLOSED - - @property - def closed_by(self) -> StreamClosedBy | None: - """ - Returns how the stream was closed, as one of StreamClosedBy. - """ - return self.state_machine.stream_closed_by - - def upgrade(self, client_side: bool) -> None: - """ - Called by the connection to indicate that this stream is the initial - request/response of an upgraded connection. Places the stream into an - appropriate state. - """ - self.config.logger.debug("Upgrading %r", self) - - assert self.stream_id == 1 - input_ = ( - StreamInputs.UPGRADE_CLIENT if client_side - else StreamInputs.UPGRADE_SERVER - ) - - # This may return events, we deliberately don't want them. - self.state_machine.process_input(input_) - - def send_headers(self, - headers: Iterable[HeaderWeaklyTyped], - encoder: Encoder, - end_stream: bool = False) -> list[HeadersFrame | ContinuationFrame | PushPromiseFrame]: - """ - Returns a list of HEADERS/CONTINUATION frames to emit as either headers - or trailers. - """ - self.config.logger.debug("Send headers %s on %r", headers, self) - - # Because encoding headers makes an irreversible change to the header - # compression context, we make the state transition before we encode - # them. - - # First, check if we're a client. If we are, no problem: if we aren't, - # we need to scan the header block to see if this is an informational - # response. - input_ = StreamInputs.SEND_HEADERS - - bytes_headers = utf8_encode_headers(headers) - - if ((not self.state_machine.client) and - is_informational_response(bytes_headers)): - if end_stream: - msg = "Cannot set END_STREAM on informational responses." - raise ProtocolError(msg) - - input_ = StreamInputs.SEND_INFORMATIONAL_HEADERS - - events = self.state_machine.process_input(input_) - - hf = HeadersFrame(self.stream_id) - hdr_validation_flags = self._build_hdr_validation_flags(events) - frames = self._build_headers_frames( - bytes_headers, encoder, hf, hdr_validation_flags, - ) - - if end_stream: - # Not a bug: the END_STREAM flag is valid on the initial HEADERS - # frame, not the CONTINUATION frames that follow. - self.state_machine.process_input(StreamInputs.SEND_END_STREAM) - frames[0].flags.add("END_STREAM") - - if self.state_machine.trailers_sent and not end_stream: - msg = "Trailers must have END_STREAM set." - raise ProtocolError(msg) - - if self.state_machine.client and self._authority is None: - self._authority = authority_from_headers(bytes_headers) - - # store request method for _initialize_content_length - self.request_method = extract_method_header(bytes_headers) - - return frames - - def push_stream_in_band(self, - related_stream_id: int, - headers: Iterable[HeaderWeaklyTyped], - encoder: Encoder) -> list[HeadersFrame | ContinuationFrame | PushPromiseFrame]: - """ - Returns a list of PUSH_PROMISE/CONTINUATION frames to emit as a pushed - stream header. Called on the stream that has the PUSH_PROMISE frame - sent on it. - """ - self.config.logger.debug("Push stream %r", self) - - # Because encoding headers makes an irreversible change to the header - # compression context, we make the state transition *first*. - - events = self.state_machine.process_input( - StreamInputs.SEND_PUSH_PROMISE, - ) - - ppf = PushPromiseFrame(self.stream_id) - ppf.promised_stream_id = related_stream_id - hdr_validation_flags = self._build_hdr_validation_flags(events) - - bytes_headers = utf8_encode_headers(headers) - - return self._build_headers_frames( - bytes_headers, encoder, ppf, hdr_validation_flags, - ) - - - def locally_pushed(self) -> list[Frame]: - """ - Mark this stream as one that was pushed by this peer. Must be called - immediately after initialization. Sends no frames, simply updates the - state machine. - """ - # This does not trigger any events. - events = self.state_machine.process_input( - StreamInputs.SEND_PUSH_PROMISE, - ) - assert not events - return [] - - def send_data(self, - data: bytes | memoryview, - end_stream: bool = False, - pad_length: int | None = None) -> list[Frame]: - """ - Prepare some data frames. Optionally end the stream. - - .. warning:: Does not perform flow control checks. - """ - self.config.logger.debug( - "Send data on %r with end stream set to %s", self, end_stream, - ) - - self.state_machine.process_input(StreamInputs.SEND_DATA) - - df = DataFrame(self.stream_id) - df.data = data - if end_stream: - self.state_machine.process_input(StreamInputs.SEND_END_STREAM) - df.flags.add("END_STREAM") - if pad_length is not None: - df.flags.add("PADDED") - df.pad_length = pad_length - - # Subtract flow_controlled_length to account for possible padding - self.outbound_flow_control_window -= df.flow_controlled_length - assert self.outbound_flow_control_window >= 0 - - return [df] - - def end_stream(self) -> list[Frame]: - """ - End a stream without sending data. - """ - self.config.logger.debug("End stream %r", self) - - self.state_machine.process_input(StreamInputs.SEND_END_STREAM) - df = DataFrame(self.stream_id) - df.flags.add("END_STREAM") - return [df] - - def advertise_alternative_service(self, field_value: bytes) -> list[Frame]: - """ - Advertise an RFC 7838 alternative service. The semantics of this are - better documented in the ``H2Connection`` class. - """ - self.config.logger.debug( - "Advertise alternative service of %r for %r", field_value, self, - ) - self.state_machine.process_input(StreamInputs.SEND_ALTERNATIVE_SERVICE) - asf = AltSvcFrame(self.stream_id) - asf.field = field_value - return [asf] - - def increase_flow_control_window(self, increment: int) -> list[Frame]: - """ - Increase the size of the flow control window for the remote side. - """ - self.config.logger.debug( - "Increase flow control window for %r by %d", - self, increment, - ) - self.state_machine.process_input(StreamInputs.SEND_WINDOW_UPDATE) - self._inbound_window_manager.window_opened(increment) - - wuf = WindowUpdateFrame(self.stream_id) - wuf.window_increment = increment - return [wuf] - - def receive_push_promise_in_band(self, - promised_stream_id: int, - headers: Iterable[Header], - header_encoding: bool | str | None) -> tuple[list[Frame], list[Event]]: - """ - Receives a push promise frame sent on this stream, pushing a remote - stream. This is called on the stream that has the PUSH_PROMISE sent - on it. - """ - self.config.logger.debug( - "Receive Push Promise on %r for remote stream %d", - self, promised_stream_id, - ) - events = self.state_machine.process_input( - StreamInputs.RECV_PUSH_PROMISE, - ) - events[0].pushed_stream_id = promised_stream_id - - hdr_validation_flags = self._build_hdr_validation_flags(events) - events[0].headers = self._process_received_headers( - headers, hdr_validation_flags, header_encoding, - ) - return [], events - - def remotely_pushed(self, pushed_headers: Iterable[Header]) -> tuple[list[Frame], list[Event]]: - """ - Mark this stream as one that was pushed by the remote peer. Must be - called immediately after initialization. Sends no frames, simply - updates the state machine. - """ - self.config.logger.debug("%r pushed by remote peer", self) - events = self.state_machine.process_input( - StreamInputs.RECV_PUSH_PROMISE, - ) - self._authority = authority_from_headers(pushed_headers) - return [], events - - def receive_headers(self, - headers: Iterable[Header], - end_stream: bool, - header_encoding: bool | str | None) -> tuple[list[Frame], list[Event]]: - """ - Receive a set of headers (or trailers). - """ - if is_informational_response(headers): - if end_stream: - msg = "Cannot set END_STREAM on informational responses" - raise ProtocolError(msg) - input_ = StreamInputs.RECV_INFORMATIONAL_HEADERS - else: - input_ = StreamInputs.RECV_HEADERS - - events = self.state_machine.process_input(input_) - - if end_stream: - es_events = self.state_machine.process_input( - StreamInputs.RECV_END_STREAM, - ) - events[0].stream_ended = es_events[0] - events += es_events - - self._initialize_content_length(headers) - - if isinstance(events[0], TrailersReceived) and not end_stream: - msg = "Trailers must have END_STREAM set" - raise ProtocolError(msg) - - hdr_validation_flags = self._build_hdr_validation_flags(events) - events[0].headers = self._process_received_headers( - headers, hdr_validation_flags, header_encoding, - ) - return [], events - - def receive_data(self, data: bytes, end_stream: bool, flow_control_len: int) -> tuple[list[Frame], list[Event]]: - """ - Receive some data. - """ - self.config.logger.debug( - "Receive data on %r with end stream %s and flow control length " - "set to %d", self, end_stream, flow_control_len, - ) - events = self.state_machine.process_input(StreamInputs.RECV_DATA) - self._inbound_window_manager.window_consumed(flow_control_len) - self._track_content_length(len(data), end_stream) - - if end_stream: - es_events = self.state_machine.process_input( - StreamInputs.RECV_END_STREAM, - ) - events[0].stream_ended = es_events[0] - events.extend(es_events) - - events[0].data = data - events[0].flow_controlled_length = flow_control_len - return [], events - - def receive_window_update(self, increment: int) -> tuple[list[Frame], list[Event]]: - """ - Handle a WINDOW_UPDATE increment. - """ - self.config.logger.debug( - "Receive Window Update on %r for increment of %d", - self, increment, - ) - events = self.state_machine.process_input( - StreamInputs.RECV_WINDOW_UPDATE, - ) - frames = [] - - # If we encounter a problem with incrementing the flow control window, - # this should be treated as a *stream* error, not a *connection* error. - # That means we need to catch the error and forcibly close the stream. - if events: - events[0].delta = increment - try: - self.outbound_flow_control_window = guard_increment_window( - self.outbound_flow_control_window, - increment, - ) - except FlowControlError: - # Ok, this is bad. We're going to need to perform a local - # reset. - event = StreamReset() - event.stream_id = self.stream_id - event.error_code = ErrorCodes.FLOW_CONTROL_ERROR - event.remote_reset = False - - events = [event] - frames = self.reset_stream(event.error_code) - - return frames, events - - def receive_continuation(self) -> None: - """ - A naked CONTINUATION frame has been received. This is always an error, - but the type of error it is depends on the state of the stream and must - transition the state of the stream, so we need to handle it. - """ - self.config.logger.debug("Receive Continuation frame on %r", self) - self.state_machine.process_input( - StreamInputs.RECV_CONTINUATION, - ) - msg = "Should not be reachable" # pragma: no cover - raise AssertionError(msg) # pragma: no cover - - def receive_alt_svc(self, frame: AltSvcFrame) -> tuple[list[Frame], list[Event]]: - """ - An Alternative Service frame was received on the stream. This frame - inherits the origin associated with this stream. - """ - self.config.logger.debug( - "Receive Alternative Service frame on stream %r", self, - ) - - # If the origin is present, RFC 7838 says we have to ignore it. - if frame.origin: - return [], [] - - events = self.state_machine.process_input( - StreamInputs.RECV_ALTERNATIVE_SERVICE, - ) - - # There are lots of situations where we want to ignore the ALTSVC - # frame. If we need to pay attention, we'll have an event and should - # fill it out. - if events: - assert isinstance(events[0], AlternativeServiceAvailable) - events[0].origin = self._authority - events[0].field_value = frame.field - - return [], events - - def reset_stream(self, error_code: ErrorCodes | int = 0) -> list[Frame]: - """ - Close the stream locally. Reset the stream with an error code. - """ - self.config.logger.debug( - "Local reset %r with error code: %d", self, error_code, - ) - self.state_machine.process_input(StreamInputs.SEND_RST_STREAM) - - rsf = RstStreamFrame(self.stream_id) - rsf.error_code = error_code - return [rsf] - - def stream_reset(self, frame: RstStreamFrame) -> tuple[list[Frame], list[Event]]: - """ - Handle a stream being reset remotely. - """ - self.config.logger.debug( - "Remote reset %r with error code: %d", self, frame.error_code, - ) - events = self.state_machine.process_input(StreamInputs.RECV_RST_STREAM) - - if events: - # We don't fire an event if this stream is already closed. - events[0].error_code = _error_code_from_int(frame.error_code) - - return [], events - - def acknowledge_received_data(self, acknowledged_size: int) -> list[Frame]: - """ - The user has informed us that they've processed some amount of data - that was received on this stream. Pass that to the window manager and - potentially return some WindowUpdate frames. - """ - self.config.logger.debug( - "Acknowledge received data with size %d on %r", - acknowledged_size, self, - ) - increment = self._inbound_window_manager.process_bytes( - acknowledged_size, - ) - if increment: - f = WindowUpdateFrame(self.stream_id) - f.window_increment = increment - return [f] - - return [] - - def _build_hdr_validation_flags(self, events: Any) -> HeaderValidationFlags: - """ - Constructs a set of header validation flags for use when normalizing - and validating header blocks. - """ - is_trailer = isinstance( - events[0], (_TrailersSent, TrailersReceived), - ) - is_response_header = isinstance( - events[0], - ( - _ResponseSent, - ResponseReceived, - InformationalResponseReceived, - ), - ) - is_push_promise = isinstance( - events[0], (PushedStreamReceived, _PushedRequestSent), - ) - - return HeaderValidationFlags( - is_client=self.state_machine.client or False, - is_trailer=is_trailer, - is_response_header=is_response_header, - is_push_promise=is_push_promise, - ) - - def _build_headers_frames(self, - headers: Iterable[Header], - encoder: Encoder, - first_frame: HeadersFrame | PushPromiseFrame, - hdr_validation_flags: HeaderValidationFlags) \ - -> list[HeadersFrame | ContinuationFrame | PushPromiseFrame]: - """ - Helper method to build headers or push promise frames. - """ - # We need to lowercase the header names, and to ensure that secure - # header fields are kept out of compression contexts. - if self.config.normalize_outbound_headers: - # also we may want to split outbound cookies to improve - # headers compression - should_split_outbound_cookies = self.config.split_outbound_cookies - - headers = normalize_outbound_headers( - headers, hdr_validation_flags, should_split_outbound_cookies, - ) - if self.config.validate_outbound_headers: - headers = validate_outbound_headers( - headers, hdr_validation_flags, - ) - - encoded_headers = encoder.encode(headers) - - # Slice into blocks of max_outbound_frame_size. Be careful with this: - # it only works right because we never send padded frames or priority - # information on the frames. Revisit this if we do. - header_blocks = [ - encoded_headers[i:i+(self.max_outbound_frame_size or 0)] - for i in range( - 0, len(encoded_headers), (self.max_outbound_frame_size or 0), - ) - ] - - frames: list[HeadersFrame | ContinuationFrame | PushPromiseFrame] = [] - first_frame.data = header_blocks[0] - frames.append(first_frame) - - for block in header_blocks[1:]: - cf = ContinuationFrame(self.stream_id) - cf.data = block - frames.append(cf) - - frames[-1].flags.add("END_HEADERS") - return frames - - def _process_received_headers(self, - headers: Iterable[Header], - header_validation_flags: HeaderValidationFlags, - header_encoding: bool | str | None) -> Iterable[Header]: - """ - When headers have been received from the remote peer, run a processing - pipeline on them to transform them into the appropriate form for - attaching to an event. - """ - if self.config.normalize_inbound_headers: - headers = normalize_inbound_headers( - headers, header_validation_flags, - ) - - if self.config.validate_inbound_headers: - headers = validate_headers(headers, header_validation_flags) - - if isinstance(header_encoding, str): - headers = _decode_headers(headers, header_encoding) - - # The above steps are all generators, so we need to concretize the - # headers now. - return list(headers) - - def _initialize_content_length(self, headers: Iterable[Header]) -> None: - """ - Checks the headers for a content-length header and initializes the - _expected_content_length field from it. It's not an error for no - Content-Length header to be present. - """ - if self.request_method == b"HEAD": - self._expected_content_length = 0 - return - - for n, v in headers: - if n == b"content-length": - try: - self._expected_content_length = int(v, 10) - except ValueError as err: - msg = f"Invalid content-length header: {v!r}" - raise ProtocolError(msg) from err - - return - - def _track_content_length(self, length: int, end_stream: bool) -> None: - """ - Update the expected content length in response to data being received. - Validates that the appropriate amount of data is sent. Always updates - the received data, but only validates the length against the - content-length header if one was sent. - - :param length: The length of the body chunk received. - :param end_stream: If this is the last body chunk received. - """ - self._actual_content_length += length - actual = self._actual_content_length - expected = self._expected_content_length - - if expected is not None: - if expected < actual: - raise InvalidBodyLengthError(expected, actual) - - if end_stream and expected != actual: - raise InvalidBodyLengthError(expected, actual) - - def _inbound_flow_control_change_from_settings(self, delta: int) -> None: - """ - We changed SETTINGS_INITIAL_WINDOW_SIZE, which means we need to - update the target window size for flow control. For our flow control - strategy, this means we need to do two things: we need to adjust the - current window size, but we also need to set the target maximum window - size to the new value. - """ - new_max_size = self._inbound_window_manager.max_window_size + delta - self._inbound_window_manager.window_opened(delta) - self._inbound_window_manager.max_window_size = new_max_size - - -def _decode_headers(headers: Iterable[HeaderWeaklyTyped], encoding: str) -> Generator[HeaderTuple, None, None]: - """ - Given an iterable of header two-tuples and an encoding, decodes those - headers using that encoding while preserving the type of the header tuple. - This ensures that the use of ``HeaderTuple`` is preserved. - """ - for header in headers: - # This function expects to work on decoded headers, which are always - # HeaderTuple objects. - assert isinstance(header, HeaderTuple) - - name, value = header - assert isinstance(name, bytes) - assert isinstance(value, bytes) - - n = name.decode(encoding) - v = value.decode(encoding) - yield header.__class__(n, v) diff --git a/serverenv/lib/python3.9/site-packages/h2/utilities.py b/serverenv/lib/python3.9/site-packages/h2/utilities.py deleted file mode 100644 index 8cafdbd..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/utilities.py +++ /dev/null @@ -1,696 +0,0 @@ -""" -h2/utilities -~~~~~~~~~~~~ - -Utility functions that do not belong in a separate module. -""" -from __future__ import annotations - -import collections -import re -from string import whitespace -from typing import TYPE_CHECKING, Any, NamedTuple - -from hpack.struct import HeaderTuple, NeverIndexedHeaderTuple - -from .exceptions import FlowControlError, ProtocolError - -if TYPE_CHECKING: # pragma: no cover - from collections.abc import Generator, Iterable - - from hpack.struct import Header, HeaderWeaklyTyped - -UPPER_RE = re.compile(b"[A-Z]") -SIGIL = ord(b":") -INFORMATIONAL_START = ord(b"1") - - -# A set of headers that are hop-by-hop or connection-specific and thus -# forbidden in HTTP/2. This list comes from RFC 7540 § 8.1.2.2. -CONNECTION_HEADERS = frozenset([ - b"connection", - b"proxy-connection", - b"keep-alive", - b"transfer-encoding", - b"upgrade", -]) - - -_ALLOWED_PSEUDO_HEADER_FIELDS = frozenset([ - b":method", - b":scheme", - b":authority", - b":path", - b":status", - b":protocol", -]) - - -_SECURE_HEADERS = frozenset([ - # May have basic credentials which are vulnerable to dictionary attacks. - b"authorization", - b"proxy-authorization", -]) - - -_REQUEST_ONLY_HEADERS = frozenset([ - b":scheme", - b":path", - b":authority", - b":method", - b":protocol", -]) - - -_RESPONSE_ONLY_HEADERS = frozenset([b":status"]) - - -# A Set of pseudo headers that are only valid if the method is -# CONNECT, see RFC 8441 § 5 -_CONNECT_REQUEST_ONLY_HEADERS = frozenset([b":protocol"]) - - -_WHITESPACE = frozenset(map(ord, whitespace)) - - -def _secure_headers(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags | None) -> Generator[Header, None, None]: - """ - Certain headers are at risk of being attacked during the header compression - phase, and so need to be kept out of header compression contexts. This - function automatically transforms certain specific headers into HPACK - never-indexed fields to ensure they don't get added to header compression - contexts. - - This function currently implements two rules: - - - 'authorization' and 'proxy-authorization' fields are automatically made - never-indexed. - - Any 'cookie' header field shorter than 20 bytes long is made - never-indexed. - - These fields are the most at-risk. These rules are inspired by Firefox - and nghttp2. - """ - for header in headers: - assert isinstance(header[0], bytes) - if header[0] in _SECURE_HEADERS or (header[0] in b"cookie" and len(header[1]) < 20): - yield NeverIndexedHeaderTuple(header[0], header[1]) - else: - yield header - - -def extract_method_header(headers: Iterable[Header]) -> bytes | None: - """ - Extracts the request method from the headers list. - """ - for k, v in headers: - if isinstance(v, bytes) and k == b":method": - return v - if isinstance(v, str) and k == ":method": - return v.encode("utf-8") # pragma: no cover - return None - - -def is_informational_response(headers: Iterable[Header]) -> bool: - """ - Searches headers list for a :status header to confirm that a given - collection of headers are an informational response. Assumes the header - are well formed and encoded as bytes: that is, that the HTTP/2 special - headers are first in the block, and so that it can stop looking when it - finds the first header field whose name does not begin with a colon. - - :param headers: The HTTP/2 headers. - :returns: A boolean indicating if this is an informational response. - """ - for n, v in headers: - if not n.startswith(b":"): - return False - if n != b":status": - # If we find a non-special header, we're done here: stop looping. - continue - # If the first digit is a 1, we've got informational headers. - return v.startswith(b"1") - return False - - -def guard_increment_window(current: int, increment: int) -> int: - """ - Increments a flow control window, guarding against that window becoming too - large. - - :param current: The current value of the flow control window. - :param increment: The increment to apply to that window. - :returns: The new value of the window. - :raises: ``FlowControlError`` - """ - # The largest value the flow control window may take. - LARGEST_FLOW_CONTROL_WINDOW = 2**31 - 1 # noqa: N806 - - new_size = current + increment - - if new_size > LARGEST_FLOW_CONTROL_WINDOW: - msg = f"May not increment flow control window past {LARGEST_FLOW_CONTROL_WINDOW}" - raise FlowControlError(msg) - - return new_size - - -def authority_from_headers(headers: Iterable[Header]) -> bytes | None: - """ - Given a header set, searches for the authority header and returns the - value. - - Note that this doesn't use indexing, so should only be called if the - headers are for a client request. Otherwise, will loop over the entire - header set, which is potentially unwise. - - :param headers: The HTTP header set. - :returns: The value of the authority header, or ``None``. - :rtype: ``bytes`` or ``None``. - """ - for n, v in headers: - if n == b":authority": - return v - - return None - - -# Flags used by the validate_headers pipeline to determine which checks -# should be applied to a given set of headers. -class HeaderValidationFlags(NamedTuple): - is_client: bool - is_trailer: bool - is_response_header: bool - is_push_promise: bool - - -def validate_headers(headers: Iterable[Header], hdr_validation_flags: HeaderValidationFlags) -> Iterable[Header]: - """ - Validates a header sequence against a set of constraints from RFC 7540. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags. - """ - # This validation logic is built on a sequence of generators that are - # iterated over to provide the final header list. This reduces some of the - # overhead of doing this checking. However, it's worth noting that this - # checking remains somewhat expensive, and attempts should be made wherever - # possible to reduce the time spent doing them. - # - # For example, we avoid tuple unpacking in loops because it represents a - # fixed cost that we don't want to spend, instead indexing into the header - # tuples. - headers = _reject_empty_header_names( - headers, hdr_validation_flags, - ) - headers = _reject_uppercase_header_fields( - headers, hdr_validation_flags, - ) - headers = _reject_surrounding_whitespace( - headers, hdr_validation_flags, - ) - headers = _reject_te( - headers, hdr_validation_flags, - ) - headers = _reject_connection_header( - headers, hdr_validation_flags, - ) - headers = _reject_pseudo_header_fields( - headers, hdr_validation_flags, - ) - headers = _check_host_authority_header( - headers, hdr_validation_flags, - ) - return _check_path_header(headers, hdr_validation_flags) - - - -def _reject_empty_header_names(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises a ProtocolError if any header names are empty (length 0). - While hpack decodes such headers without errors, they are semantically - forbidden in HTTP, see RFC 7230, stating that they must be at least one - character long. - """ - for header in headers: - if len(header[0]) == 0: - msg = "Received header name with zero length." - raise ProtocolError(msg) - yield header - - -def _reject_uppercase_header_fields(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises a ProtocolError if any uppercase character is found in a header - block. - """ - for header in headers: - if UPPER_RE.search(header[0]): - msg = f"Received uppercase header name {header[0]!r}." - raise ProtocolError(msg) - yield header - - -def _reject_surrounding_whitespace(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises a ProtocolError if any header name or value is surrounded by - whitespace characters. - """ - # For compatibility with RFC 7230 header fields, we need to allow the field - # value to be an empty string. This is ludicrous, but technically allowed. - # The field name may not be empty, though, so we can safely assume that it - # must have at least one character in it and throw exceptions if it - # doesn't. - for header in headers: - if header[0][0] in _WHITESPACE or header[0][-1] in _WHITESPACE: - msg = f"Received header name surrounded by whitespace {header[0]!r}" - raise ProtocolError(msg) - if header[1] and ((header[1][0] in _WHITESPACE) or - (header[1][-1] in _WHITESPACE)): - msg = f"Received header value surrounded by whitespace {header[1]!r}" - raise ProtocolError(msg) - yield header - - -def _reject_te(headers: Iterable[Header], hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises a ProtocolError if the TE header is present in a header block and - its value is anything other than "trailers". - """ - for header in headers: - if header[0] == b"te" and header[1].lower() != b"trailers": - msg = f"Invalid value for TE header: {header[1]!r}" - raise ProtocolError(msg) - - yield header - - -def _reject_connection_header(headers: Iterable[Header], hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises a ProtocolError if the Connection header is present in a header - block. - """ - for header in headers: - if header[0] in CONNECTION_HEADERS: - msg = f"Connection-specific header field present: {header[0]!r}." - raise ProtocolError(msg) - - yield header - - -def _assert_header_in_set(bytes_header: bytes, - header_set: set[bytes | str] | set[bytes] | set[str]) -> None: - """ - Given a set of header names, checks whether the string or byte version of - the header name is present. Raises a Protocol error with the appropriate - error if it's missing. - """ - if bytes_header not in header_set: - msg = f"Header block missing mandatory {bytes_header!r} header" - raise ProtocolError(msg) - - -def _reject_pseudo_header_fields(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises a ProtocolError if duplicate pseudo-header fields are found in a - header block or if a pseudo-header field appears in a block after an - ordinary header field. - - Raises a ProtocolError if pseudo-header fields are found in trailers. - """ - seen_pseudo_header_fields = set() - seen_regular_header = False - method = None - - for header in headers: - if header[0][0] == SIGIL: - if header[0] in seen_pseudo_header_fields: - msg = f"Received duplicate pseudo-header field {header[0]!r}" - raise ProtocolError(msg) - - seen_pseudo_header_fields.add(header[0]) - - if seen_regular_header: - msg = f"Received pseudo-header field out of sequence: {header[0]!r}" - raise ProtocolError(msg) - - if header[0] not in _ALLOWED_PSEUDO_HEADER_FIELDS: - msg = f"Received custom pseudo-header field {header[0]!r}" - raise ProtocolError(msg) - - if header[0] in b":method": - method = header[1] - - else: - seen_regular_header = True - - yield header - - # Check the pseudo-headers we got to confirm they're acceptable. - _check_pseudo_header_field_acceptability( - seen_pseudo_header_fields, method, hdr_validation_flags, - ) - - -def _check_pseudo_header_field_acceptability(pseudo_headers: set[bytes | str] | set[bytes] | set[str], - method: bytes | None, - hdr_validation_flags: HeaderValidationFlags) -> None: - """ - Given the set of pseudo-headers present in a header block and the - validation flags, confirms that RFC 7540 allows them. - """ - # Pseudo-header fields MUST NOT appear in trailers - RFC 7540 § 8.1.2.1 - if hdr_validation_flags.is_trailer and pseudo_headers: - msg = f"Received pseudo-header in trailer {pseudo_headers}" - raise ProtocolError(msg) - - # If ':status' pseudo-header is not there in a response header, reject it. - # Similarly, if ':path', ':method', or ':scheme' are not there in a request - # header, reject it. Additionally, if a response contains any request-only - # headers or vice-versa, reject it. - # Relevant RFC section: RFC 7540 § 8.1.2.4 - # https://tools.ietf.org/html/rfc7540#section-8.1.2.4 - if hdr_validation_flags.is_response_header: - _assert_header_in_set(b":status", pseudo_headers) - invalid_response_headers = pseudo_headers & _REQUEST_ONLY_HEADERS - if invalid_response_headers: - msg = f"Encountered request-only headers {invalid_response_headers}" - raise ProtocolError(msg) - elif (not hdr_validation_flags.is_response_header and - not hdr_validation_flags.is_trailer): - # This is a request, so we need to have seen :path, :method, and - # :scheme. - _assert_header_in_set(b":path", pseudo_headers) - _assert_header_in_set(b":method", pseudo_headers) - _assert_header_in_set(b":scheme", pseudo_headers) - invalid_request_headers = pseudo_headers & _RESPONSE_ONLY_HEADERS - if invalid_request_headers: - msg = f"Encountered response-only headers {invalid_request_headers}" - raise ProtocolError(msg) - if method != b"CONNECT": - invalid_headers = pseudo_headers & _CONNECT_REQUEST_ONLY_HEADERS - if invalid_headers: - msg = f"Encountered connect-request-only headers {invalid_headers!r}" - raise ProtocolError(msg) - - -def _validate_host_authority_header(headers: Iterable[Header]) -> Generator[Header, None, None]: - """ - Given the :authority and Host headers from a request block that isn't - a trailer, check that: - 1. At least one of these headers is set. - 2. If both headers are set, they match. - - :param headers: The HTTP header set. - :raises: ``ProtocolError`` - """ - # We use None as a sentinel value. Iterate over the list of headers, - # and record the value of these headers (if present). We don't need - # to worry about receiving duplicate :authority headers, as this is - # enforced by the _reject_pseudo_header_fields() pipeline. - # - # TODO: We should also guard against receiving duplicate Host headers, - # and against sending duplicate headers. - authority_header_val = None - host_header_val = None - - for header in headers: - if header[0] == b":authority": - authority_header_val = header[1] - elif header[0] == b"host": - host_header_val = header[1] - - yield header - - # If we have not-None values for these variables, then we know we saw - # the corresponding header. - authority_present = (authority_header_val is not None) - host_present = (host_header_val is not None) - - # It is an error for a request header block to contain neither - # an :authority header nor a Host header. - if not authority_present and not host_present: - msg = "Request header block does not have an :authority or Host header." - raise ProtocolError(msg) - - # If we receive both headers, they should definitely match. - if authority_present and host_present and authority_header_val != host_header_val: - msg = ( - "Request header block has mismatched :authority and " - f"Host headers: {authority_header_val!r} / {host_header_val!r}" - ) - raise ProtocolError(msg) - - -def _check_host_authority_header(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises a ProtocolError if a header block arrives that does not contain an - :authority or a Host header, or if a header block contains both fields, - but their values do not match. - """ - # We only expect to see :authority and Host headers on request header - # blocks that aren't trailers, so skip this validation if this is a - # response header or we're looking at trailer blocks. - skip_validation = ( - hdr_validation_flags.is_response_header or - hdr_validation_flags.is_trailer - ) - if skip_validation: - return (h for h in headers) - - return _validate_host_authority_header(headers) - - -def _check_path_header(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raise a ProtocolError if a header block arrives or is sent that contains an - empty :path header. - """ - def inner() -> Generator[Header, None, None]: - for header in headers: - if header[0] == b":path" and not header[1]: - msg = "An empty :path header is forbidden" - raise ProtocolError(msg) - - yield header - - # We only expect to see :authority and Host headers on request header - # blocks that aren't trailers, so skip this validation if this is a - # response header or we're looking at trailer blocks. - skip_validation = ( - hdr_validation_flags.is_response_header or - hdr_validation_flags.is_trailer - ) - if skip_validation: - return (h for h in headers) - return inner() - - -def _to_bytes(v: bytes | str) -> bytes: - """ - Given an assumed `str` (or anything that supports `.encode()`), - encodes it using utf-8 into bytes. Returns the unmodified object - if it is already a `bytes` object. - """ - return v if isinstance(v, bytes) else v.encode("utf-8") - - -def utf8_encode_headers(headers: Iterable[HeaderWeaklyTyped]) -> list[Header]: - """ - Given an iterable of header two-tuples, rebuilds that as a list with the - header names and values encoded as utf-8 bytes. This function produces - tuples that preserve the original type of the header tuple for tuple and - any ``HeaderTuple``. - """ - encoded_headers: list[Header] = [] - for header in headers: - h = (_to_bytes(header[0]), _to_bytes(header[1])) - if isinstance(header, HeaderTuple): - encoded_headers.append(header.__class__(h[0], h[1])) - else: - encoded_headers.append(h) - return encoded_headers - - -def _lowercase_header_names(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags | None) -> Generator[Header, None, None]: - """ - Given an iterable of header two-tuples, rebuilds that iterable with the - header names lowercased. This generator produces tuples that preserve the - original type of the header tuple for tuple and any ``HeaderTuple``. - """ - for header in headers: - if isinstance(header, HeaderTuple): - yield header.__class__(header[0].lower(), header[1]) - else: - yield (header[0].lower(), header[1]) - - -def _strip_surrounding_whitespace(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags | None) -> Generator[Header, None, None]: - """ - Given an iterable of header two-tuples, strip both leading and trailing - whitespace from both header names and header values. This generator - produces tuples that preserve the original type of the header tuple for - tuple and any ``HeaderTuple``. - """ - for header in headers: - if isinstance(header, HeaderTuple): - yield header.__class__(header[0].strip(), header[1].strip()) - else: - yield (header[0].strip(), header[1].strip()) - - -def _strip_connection_headers(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags | None) -> Generator[Header, None, None]: - """ - Strip any connection headers as per RFC7540 § 8.1.2.2. - """ - for header in headers: - if header[0] not in CONNECTION_HEADERS: - yield header - - -def _check_sent_host_authority_header(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Raises an InvalidHeaderBlockError if we try to send a header block - that does not contain an :authority or a Host header, or if - the header block contains both fields, but their values do not match. - """ - # We only expect to see :authority and Host headers on request header - # blocks that aren't trailers, so skip this validation if this is a - # response header or we're looking at trailer blocks. - skip_validation = ( - hdr_validation_flags.is_response_header or - hdr_validation_flags.is_trailer - ) - if skip_validation: - return (h for h in headers) - - return _validate_host_authority_header(headers) - - -def _combine_cookie_fields(headers: Iterable[Header], hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - RFC 7540 § 8.1.2.5 allows HTTP/2 clients to split the Cookie header field, - which must normally appear only once, into multiple fields for better - compression. However, they MUST be joined back up again when received. - This normalization step applies that transform. The side-effect is that - all cookie fields now appear *last* in the header block. - """ - # There is a problem here about header indexing. Specifically, it's - # possible that all these cookies are sent with different header indexing - # values. At this point it shouldn't matter too much, so we apply our own - # logic and make them never-indexed. - cookies: list[bytes] = [] - for header in headers: - if header[0] == b"cookie": - cookies.append(header[1]) - else: - yield header - if cookies: - cookie_val = b"; ".join(cookies) - yield NeverIndexedHeaderTuple(b"cookie", cookie_val) - - -def _split_outbound_cookie_fields(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags | None) -> Generator[Header, None, None]: - """ - RFC 7540 § 8.1.2.5 allows for better compression efficiency, - to split the Cookie header field into separate header fields - - We want to do it for outbound requests, as we are doing for - inbound. - """ - for header in headers: - assert isinstance(header[0], bytes) - assert isinstance(header[1], bytes) - if header[0] == b"cookie": - for cookie_val in header[1].split(b"; "): - if isinstance(header, HeaderTuple): - yield header.__class__(header[0], cookie_val) - else: - yield header[0], cookie_val - else: - yield header - - -def normalize_outbound_headers(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags | None, - should_split_outbound_cookies: bool=False) -> Generator[Header, None, None]: - """ - Normalizes a header sequence that we are about to send. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags. - :param should_split_outbound_cookies: boolean flag - """ - headers = _lowercase_header_names(headers, hdr_validation_flags) - if should_split_outbound_cookies: - headers = _split_outbound_cookie_fields(headers, hdr_validation_flags) - headers = _strip_surrounding_whitespace(headers, hdr_validation_flags) - headers = _strip_connection_headers(headers, hdr_validation_flags) - return _secure_headers(headers, hdr_validation_flags) - - - -def normalize_inbound_headers(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Normalizes a header sequence that we have received. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags - """ - return _combine_cookie_fields(headers, hdr_validation_flags) - - -def validate_outbound_headers(headers: Iterable[Header], - hdr_validation_flags: HeaderValidationFlags) -> Generator[Header, None, None]: - """ - Validates and normalizes a header sequence that we are about to send. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags. - """ - headers = _reject_te( - headers, hdr_validation_flags, - ) - headers = _reject_connection_header( - headers, hdr_validation_flags, - ) - headers = _reject_pseudo_header_fields( - headers, hdr_validation_flags, - ) - headers = _check_sent_host_authority_header( - headers, hdr_validation_flags, - ) - return _check_path_header(headers, hdr_validation_flags) - - - -class SizeLimitDict(collections.OrderedDict[int, Any]): - - def __init__(self, *args: dict[int, int], **kwargs: Any) -> None: - self._size_limit = kwargs.pop("size_limit", None) - super().__init__(*args, **kwargs) - - self._check_size_limit() - - def __setitem__(self, key: int, value: Any | int) -> None: - super().__setitem__(key, value) - - self._check_size_limit() - - def _check_size_limit(self) -> None: - if self._size_limit is not None: - while len(self) > self._size_limit: - self.popitem(last=False) diff --git a/serverenv/lib/python3.9/site-packages/h2/windows.py b/serverenv/lib/python3.9/site-packages/h2/windows.py deleted file mode 100644 index 0efdd9f..0000000 --- a/serverenv/lib/python3.9/site-packages/h2/windows.py +++ /dev/null @@ -1,133 +0,0 @@ -""" -h2/windows -~~~~~~~~~~ - -Defines tools for managing HTTP/2 flow control windows. - -The objects defined in this module are used to automatically manage HTTP/2 -flow control windows. Specifically, they keep track of what the size of the -window is, how much data has been consumed from that window, and how much data -the user has already used. It then implements a basic algorithm that attempts -to manage the flow control window without user input, trying to ensure that it -does not emit too many WINDOW_UPDATE frames. -""" -from __future__ import annotations - -from .exceptions import FlowControlError - -# The largest acceptable value for a HTTP/2 flow control window. -LARGEST_FLOW_CONTROL_WINDOW = 2**31 - 1 - - -class WindowManager: - """ - A basic HTTP/2 window manager. - - :param max_window_size: The maximum size of the flow control window. - :type max_window_size: ``int`` - """ - - def __init__(self, max_window_size: int) -> None: - assert max_window_size <= LARGEST_FLOW_CONTROL_WINDOW - self.max_window_size = max_window_size - self.current_window_size = max_window_size - self._bytes_processed = 0 - - def window_consumed(self, size: int) -> None: - """ - We have received a certain number of bytes from the remote peer. This - necessarily shrinks the flow control window! - - :param size: The number of flow controlled bytes we received from the - remote peer. - :type size: ``int`` - :returns: Nothing. - :rtype: ``None`` - """ - self.current_window_size -= size - if self.current_window_size < 0: - msg = "Flow control window shrunk below 0" - raise FlowControlError(msg) - - def window_opened(self, size: int) -> None: - """ - The flow control window has been incremented, either because of manual - flow control management or because of the user changing the flow - control settings. This can have the effect of increasing what we - consider to be the "maximum" flow control window size. - - This does not increase our view of how many bytes have been processed, - only of how much space is in the window. - - :param size: The increment to the flow control window we received. - :type size: ``int`` - :returns: Nothing - :rtype: ``None`` - """ - self.current_window_size += size - - if self.current_window_size > LARGEST_FLOW_CONTROL_WINDOW: - msg = f"Flow control window mustn't exceed {LARGEST_FLOW_CONTROL_WINDOW}" - raise FlowControlError(msg) - - self.max_window_size = max(self.current_window_size, self.max_window_size) - - def process_bytes(self, size: int) -> int | None: - """ - The application has informed us that it has processed a certain number - of bytes. This may cause us to want to emit a window update frame. If - we do want to emit a window update frame, this method will return the - number of bytes that we should increment the window by. - - :param size: The number of flow controlled bytes that the application - has processed. - :type size: ``int`` - :returns: The number of bytes to increment the flow control window by, - or ``None``. - :rtype: ``int`` or ``None`` - """ - self._bytes_processed += size - return self._maybe_update_window() - - def _maybe_update_window(self) -> int | None: - """ - Run the algorithm. - - Our current algorithm can be described like this. - - 1. If no bytes have been processed, we immediately return 0. There is - no meaningful way for us to hand space in the window back to the - remote peer, so let's not even try. - 2. If there is no space in the flow control window, and we have - processed at least 1024 bytes (or 1/4 of the window, if the window - is smaller), we will emit a window update frame. This is to avoid - the risk of blocking a stream altogether. - 3. If there is space in the flow control window, and we have processed - at least 1/2 of the window worth of bytes, we will emit a window - update frame. This is to minimise the number of window update frames - we have to emit. - - In a healthy system with large flow control windows, this will - irregularly emit WINDOW_UPDATE frames. This prevents us starving the - connection by emitting eleventy bajillion WINDOW_UPDATE frames, - especially in situations where the remote peer is sending a lot of very - small DATA frames. - """ - # TODO: Can the window be smaller than 1024 bytes? If not, we can - # streamline this algorithm. - if not self._bytes_processed: - return None - - max_increment = (self.max_window_size - self.current_window_size) - increment = 0 - - # Note that, even though we may increment less than _bytes_processed, - # we still want to set it to zero whenever we emit an increment. This - # is because we'll always increment up to the maximum we can. - if ((self.current_window_size == 0) and ( - self._bytes_processed > min(1024, self.max_window_size // 4))) or self._bytes_processed >= (self.max_window_size // 2): - increment = min(self._bytes_processed, max_increment) - self._bytes_processed = 0 - - self.current_window_size += increment - return increment diff --git a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/LICENSE b/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/LICENSE deleted file mode 100644 index d24c351..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Cory Benfield - -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/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/METADATA deleted file mode 100644 index a26a1f0..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/METADATA +++ /dev/null @@ -1,118 +0,0 @@ -Metadata-Version: 2.2 -Name: hpack -Version: 4.1.0 -Summary: Pure-Python HPACK header encoding -Author-email: Cory Benfield -Maintainer-email: Thomas Kriechbaumer -License: The MIT License (MIT) - - Copyright (c) 2014 Cory Benfield - - 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. - -Project-URL: Homepage, https://github.com/python-hyper/hpack/ -Project-URL: Bug Reports, https://github.com/python-hyper/hpack/issues -Project-URL: Source, https://github.com/python-hyper/hpack/ -Project-URL: Documentation, https://python-hyper.org/ -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.9 -Description-Content-Type: text/x-rst -License-File: LICENSE - -======================================== -hpack: HTTP/2 Header Encoding for Python -======================================== - -.. image:: https://github.com/python-hyper/hpack/workflows/CI/badge.svg - :target: https://github.com/python-hyper/hpack/actions - :alt: Build Status -.. image:: https://codecov.io/gh/python-hyper/hpack/branch/master/graph/badge.svg - :target: https://codecov.io/gh/python-hyper/hpack - :alt: Code Coverage -.. image:: https://readthedocs.org/projects/hpack/badge/?version=latest - :target: https://hpack.readthedocs.io/en/latest/ - :alt: Documentation Status -.. image:: https://img.shields.io/badge/chat-join_now-brightgreen.svg - :target: https://gitter.im/python-hyper/community - :alt: Chat community - -.. image:: https://raw.github.com/python-hyper/documentation/master/source/logo/hyper-black-bg-white.png - -This module contains a pure-Python HTTP/2 header encoding (HPACK) logic for use -in Python programs that implement HTTP/2. - -Documentation -============= - -Documentation is available at https://hpack.readthedocs.io . - -Quickstart: - -.. code-block:: python - - from hpack import Encoder, Decoder - - headers = [ - (':method', 'GET'), - (':path', '/jimiscool/'), - ('X-Some-Header', 'some_value'), - ] - - e = Encoder() - encoded_bytes = e.encode(headers) - - d = Decoder() - decoded_headers = d.decode(encoded_bytes) - - -Contributing -============ - -``hpack`` welcomes contributions from anyone! Unlike many other projects we are -happy to accept cosmetic contributions and small contributions, in addition to -large feature requests and changes. - -Before you contribute (either by opening an issue or filing a pull request), -please `read the contribution guidelines`_. - -.. _read the contribution guidelines: http://hyper.readthedocs.org/en/development/contributing.html - -License -======= - -``hpack`` is made available under the MIT License. For more details, see the -``LICENSE`` file in the repository. - -Authors -======= - -``hpack`` is maintained by Cory Benfield, with contributions from others. For -more details about the contributors, please see ``CONTRIBUTORS.rst``. diff --git a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/RECORD deleted file mode 100644 index cc72410..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/RECORD +++ /dev/null @@ -1,23 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/exceptions.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/hpack.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/huffman.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/huffman_constants.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/huffman_table.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/struct.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hpack/table.cpython-39.pyc,, -hpack-4.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -hpack-4.1.0.dist-info/LICENSE,sha256=djqTQqBN9iBGydx0ilKHk06wpTMcaGOzygruIOGMtO0,1080 -hpack-4.1.0.dist-info/METADATA,sha256=Q1gXKCgIVHBpDQfF7-ueVDMd1VuqTHFaKPtOLkgm4uY,4618 -hpack-4.1.0.dist-info/RECORD,, -hpack-4.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91 -hpack-4.1.0.dist-info/top_level.txt,sha256=nyrZLbQo-0nC6ot3YO_109pkUiTtK1M0wUJfLHuQceE,6 -hpack/__init__.py,sha256=VYm8vhs7h2QrWMSX6e-kEDtzJYzA3jFgdt_VQwP2Ygg,597 -hpack/exceptions.py,sha256=Xqy8viqvKKHByQ7Io8Fp-HPlDP3T7RM9aplPSxdr9jI,1107 -hpack/hpack.py,sha256=BqvSSOZ3QAgH5j5ZRX5Mp3cSxx5qe_o4g_eO4xHMA8I,24514 -hpack/huffman.py,sha256=xuGZFAqLcnxrSEucjqNQOhJXxdGJ5PG1hDgImGi_qOM,2383 -hpack/huffman_constants.py,sha256=4PhOMel5mN0askFRrn4nVpJ_CTOUhO1qbFRO6u_If2M,4570 -hpack/huffman_table.py,sha256=3dJuUmeP6EocfHC-ULhzkmBToXn1lP2HG6gwP_eBmbY,168650 -hpack/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -hpack/struct.py,sha256=NXS2O84u2zHdokjutf-9ISZ7h1qyZLTPE-TKpcWl1T4,1463 -hpack/table.py,sha256=UAk39fUkM_r8dnBKODL_qGr9_wROnKQVB2EDP2ADJkI,10000 diff --git a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/WHEEL deleted file mode 100644 index 505164b..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (75.8.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/top_level.txt b/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/top_level.txt deleted file mode 100644 index 1a0ac48..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack-4.1.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -hpack diff --git a/serverenv/lib/python3.9/site-packages/hpack/__init__.py b/serverenv/lib/python3.9/site-packages/hpack/__init__.py deleted file mode 100644 index 70909f7..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -HTTP/2 header encoding for Python. -""" -from __future__ import annotations - -from .exceptions import HPACKDecodingError, HPACKError, InvalidTableIndex, InvalidTableIndexError, InvalidTableSizeError, OversizedHeaderListError -from .hpack import Decoder, Encoder -from .struct import HeaderTuple, NeverIndexedHeaderTuple - -__all__ = [ - "Decoder", - "Encoder", - "HPACKDecodingError", - "HPACKError", - "HeaderTuple", - "InvalidTableIndex", - "InvalidTableIndexError", - "InvalidTableSizeError", - "NeverIndexedHeaderTuple", - "OversizedHeaderListError", -] - -__version__ = "4.1.0" diff --git a/serverenv/lib/python3.9/site-packages/hpack/exceptions.py b/serverenv/lib/python3.9/site-packages/hpack/exceptions.py deleted file mode 100644 index 51f5083..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/exceptions.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Exceptions used in hpack. -""" -from __future__ import annotations - - -class HPACKError(Exception): - """ - The base class for all ``hpack`` exceptions. - """ - - - -class HPACKDecodingError(HPACKError): - """ - An error has been encountered while performing HPACK decoding. - """ - - - -class InvalidTableIndexError(HPACKDecodingError): - """ - An invalid table index was received. - - .. versionadded:: 4.1.0 - """ - -class InvalidTableIndex(InvalidTableIndexError): # noqa: N818 - """ - An invalid table index was received. - - .. deprecated:: 4.1.0 - Renamed to :class:`InvalidTableIndexError`, use it instead. - """ - - -class OversizedHeaderListError(HPACKDecodingError): - """ - A header list that was larger than we allow has been received. This may be - a DoS attack. - - .. versionadded:: 2.3.0 - """ - - -class InvalidTableSizeError(HPACKDecodingError): - """ - An attempt was made to change the decoder table size to a value larger than - allowed, or the list was shrunk and the remote peer didn't shrink their - table size. - - .. versionadded:: 3.0.0 - """ diff --git a/serverenv/lib/python3.9/site-packages/hpack/hpack.py b/serverenv/lib/python3.9/site-packages/hpack/hpack.py deleted file mode 100644 index caa018c..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/hpack.py +++ /dev/null @@ -1,654 +0,0 @@ -""" -Implements the HPACK header compression algorithm as detailed by RFC 7541. -""" -from __future__ import annotations - -import logging -from typing import TYPE_CHECKING, Any - -from .exceptions import HPACKDecodingError, InvalidTableSizeError, OversizedHeaderListError -from .huffman import HuffmanEncoder -from .huffman_constants import REQUEST_CODES, REQUEST_CODES_LENGTH -from .huffman_table import decode_huffman -from .struct import HeaderTuple, HeaderWeaklyTyped, NeverIndexedHeaderTuple -from .table import HeaderTable, table_entry_size - -if TYPE_CHECKING: - from collections.abc import Iterable # pragma: no cover - -log = logging.getLogger(__name__) - -INDEX_NONE = b"\x00" -INDEX_NEVER = b"\x10" -INDEX_INCREMENTAL = b"\x40" - -# Precompute 2^i for 1-8 for use in prefix calcs. -# Zero index is not used but there to save a subtraction -# as prefix numbers are not zero indexed. -_PREFIX_BIT_MAX_NUMBERS = [(2 ** i) - 1 for i in range(9)] - -# We default the maximum header list we're willing to accept to 64kB. That's a -# lot of headers, but if applications want to raise it they can do. -DEFAULT_MAX_HEADER_LIST_SIZE = 2 ** 16 - - -def _unicode_if_needed(header: HeaderWeaklyTyped, raw: bool) -> HeaderTuple: - """ - Provides a header as a unicode string if raw is False, otherwise returns - it as a bytestring. - """ - name = bytes(header[0]) # type: ignore - value = bytes(header[1]) # type: ignore - - if not raw: - return header.__class__(name.decode("utf-8"), value.decode("utf-8")) # type: ignore - return header.__class__(name, value) # type: ignore - - -def encode_integer(integer: int, prefix_bits: int) -> bytearray: - """ - Encodes an integer according to the wacky integer encoding rules - defined in the HPACK spec. - """ - log.debug("Encoding %d with %d bits", integer, prefix_bits) - - if integer < 0: - msg = f"Can only encode positive integers, got {integer}" - raise ValueError(msg) - - if prefix_bits < 1 or prefix_bits > 8: - msg = f"Prefix bits must be between 1 and 8, got {prefix_bits}" - raise ValueError(msg) - - max_number = _PREFIX_BIT_MAX_NUMBERS[prefix_bits] - - if integer < max_number: - return bytearray([integer]) # Seriously? - elements = [max_number] - integer -= max_number - - while integer >= 128: - elements.append((integer & 127) + 128) - integer >>= 7 - - elements.append(integer) - - return bytearray(elements) - - -def decode_integer(data: bytes, prefix_bits: int) -> tuple[int, int]: - """ - Decodes an integer according to the wacky integer encoding rules - defined in the HPACK spec. Returns a tuple of the decoded integer and the - number of bytes that were consumed from ``data`` in order to get that - integer. - """ - if prefix_bits < 1 or prefix_bits > 8: - msg = f"Prefix bits must be between 1 and 8, got {prefix_bits}" - raise ValueError(msg) - - max_number = _PREFIX_BIT_MAX_NUMBERS[prefix_bits] - index = 1 - shift = 0 - mask = (0xFF >> (8 - prefix_bits)) - - try: - number = data[0] & mask - if number == max_number: - while True: - next_byte = data[index] - index += 1 - - if next_byte >= 128: - number += (next_byte - 128) << shift - else: - number += next_byte << shift - break - shift += 7 - - except IndexError as err: - msg = f"Unable to decode HPACK integer representation from {data!r}" - raise HPACKDecodingError(msg) from err - - log.debug("Decoded %d, consumed %d bytes", number, index) - - return number, index - - -def _dict_to_iterable(header_dict: dict[bytes | str, bytes | str]) \ - -> Iterable[tuple[bytes | str, bytes | str]]: - """ - Converts a dictionary to an iterable of key-value tuples. This is a - HPACK-specific function because it pulls "special-headers" out first and - then emits them. - """ - if not isinstance(header_dict, dict): # pragma: no cover - msg = f"header_dict not a dict, but {type(header_dict)}" - raise TypeError(msg) - - keys = sorted( - header_dict.keys(), - key=lambda k: not _to_bytes(k).startswith(b":"), - ) - for key in keys: - yield key, header_dict[key] - - -def _to_bytes(value: bytes | str | Any) -> bytes: - """ - Convert anything to bytes through a UTF-8 encoded string - """ - t = type(value) - if t is bytes: - return value # type: ignore - if t is not str: - value = str(value) - return value.encode("utf-8") # type: ignore - - -class Encoder: - """ - An HPACK encoder object. This object takes HTTP headers and emits encoded - HTTP/2 header blocks. - """ - - def __init__(self) -> None: - self.header_table = HeaderTable() - self.huffman_coder = HuffmanEncoder( - REQUEST_CODES, REQUEST_CODES_LENGTH, - ) - self.table_size_changes: list[int] = [] - - @property - def header_table_size(self) -> int: - """ - Controls the size of the HPACK header table. - """ - return self.header_table.maxsize - - @header_table_size.setter - def header_table_size(self, value: int) -> None: - self.header_table.maxsize = value - if self.header_table.resized: - self.table_size_changes.append(value) - - def encode(self, - headers: Iterable[\ - HeaderTuple | \ - tuple[bytes | str, bytes | str] | \ - tuple[bytes | str, bytes | str, bool | None]] | \ - dict[bytes | str, bytes | str], - huffman: bool = True) -> bytes: - """ - Takes a set of headers and encodes them into a HPACK-encoded header - block. - - :param headers: The headers to encode. Must be either an iterable of - tuples, an iterable of :class:`HeaderTuple - `, or a ``dict``. - - If an iterable of tuples, the tuples may be either - two-tuples or three-tuples. If they are two-tuples, the - tuples must be of the format ``(name, value)``. If they - are three-tuples, they must be of the format - ``(name, value, sensitive)``, where ``sensitive`` is a - boolean value indicating whether the header should be - added to header tables anywhere. If not present, - ``sensitive`` defaults to ``False``. - - If an iterable of :class:`HeaderTuple - `, the tuples must always be - two-tuples. Instead of using ``sensitive`` as a third - tuple entry, use :class:`NeverIndexedHeaderTuple - ` to request that - the field never be indexed. - - .. warning:: HTTP/2 requires that all special headers - (headers whose names begin with ``:`` characters) - appear at the *start* of the header block. While - this method will ensure that happens for ``dict`` - subclasses, callers using any other iterable of - tuples **must** ensure they place their special - headers at the start of the iterable. - - For efficiency reasons users should prefer to use - iterables of two-tuples: fixing the ordering of - dictionary headers is an expensive operation that - should be avoided if possible. - - :param huffman: (optional) Whether to Huffman-encode any header sent as - a literal value. Except for use when debugging, it is - recommended that this be left enabled. - - :returns: A bytestring containing the HPACK-encoded header block. - """ - # Transforming the headers into a header block is a procedure that can - # be modeled as a chain or pipe. First, the headers are encoded. This - # encoding can be done a number of ways. If the header name-value pair - # are already in the header table we can represent them using the - # indexed representation: the same is true if they are in the static - # table. Otherwise, a literal representation will be used. - header_block = [] - - # Before we begin, if the header table size has been changed we need - # to signal all changes since last emission appropriately. - if self.header_table.resized: - header_block.append(self._encode_table_size_change()) - self.header_table.resized = False - - if isinstance(headers, dict): - # Turn the headers into a list of tuples if possible. This is the - # natural way to interact with them in HPACK. Because dictionaries are - # un-ordered, we need to make sure we grab the "special" headers first. - hpack_headers = _dict_to_iterable(headers) - else: - """ - Assume headers is an iterable of HeaderTuples, or plain 2-tuples, or plain 3-tuples: - - examples: - [ - HeaderTuple(':method', 'GET'), - NeverIndexedHeaderTuple('customkey', 'sensitiveinfo'), - ] - or - [ - (':method', 'GET'), - ('customkey', 'some-data'), - ] - or - [ - (':method', 'GET', True), - ('customkey', 'sensitiveinfo', True), - ] - """ - hpack_headers = iter(headers) # type: ignore - - # Add each header to the header block - for header in hpack_headers: - sensitive = False - if isinstance(header, HeaderTuple): - # HeaderTuple implies it's a 2-tuple with the sensitive information stored as instance attribute - sensitive = not header.indexable - elif len(header) > 2: - sensitive = header[2] - - new_header = (_to_bytes(header[0]), _to_bytes(header[1])) - header_block.append(self.add(new_header, sensitive, huffman)) - - encoded = b"".join(header_block) - - log.debug("Encoded header block to %s", encoded) - - return encoded - - def add(self, to_add: tuple[bytes, bytes], sensitive: bool, huffman: bool = False) -> bytes: - """ - Serializes a header key-value tuple. - """ - log.debug( - "Adding %s to the header table, sensitive:%s, huffman:%s", - to_add, - sensitive, - huffman, - ) - - name, value = to_add - - # Set our indexing mode - indexbit = INDEX_INCREMENTAL if not sensitive else INDEX_NEVER - - # Search for a matching header in the header table. - match = self.header_table.search(name, value) - - if match is None: - # Not in the header table. Encode using the literal syntax, - # and add it to the header table. - encoded = self._encode_literal(name, value, indexbit, huffman) - if not sensitive: - self.header_table.add(name, value) - return encoded - - # The header is in the table, break out the values. If we matched - # perfectly, we can use the indexed representation: otherwise we - # can use the indexed literal. - index, name, perfect = match - - if perfect: - # Indexed representation. - encoded = self._encode_indexed(index) - else: - # Indexed literal. We are going to add header to the - # header table unconditionally. It is a future todo to - # filter out headers which are known to be ineffective for - # indexing since they just take space in the table and - # pushed out other valuable headers. - encoded = self._encode_indexed_literal( - index, value, indexbit, huffman, - ) - if not sensitive: - self.header_table.add(name, value) - - return encoded - - def _encode_indexed(self, index: int) -> bytes: - """ - Encodes a header using the indexed representation. - """ - field = encode_integer(index, 7) - field[0] |= 0x80 # we set the top bit - return bytes(field) - - def _encode_literal(self, name: bytes, value: bytes, indexbit: bytes, huffman: bool = False) -> bytes: - """ - Encodes a header with a literal name and literal value. If ``indexing`` - is True, the header will be added to the header table: otherwise it - will not. - """ - if huffman: - name = self.huffman_coder.encode(name) - value = self.huffman_coder.encode(value) - - name_len = encode_integer(len(name), 7) - value_len = encode_integer(len(value), 7) - - if huffman: - name_len[0] |= 0x80 - value_len[0] |= 0x80 - - return b"".join( - [indexbit, bytes(name_len), name, bytes(value_len), value], - ) - - def _encode_indexed_literal(self, index: int, value: bytes, indexbit: bytes, huffman: bool = False) -> bytes: - """ - Encodes a header with an indexed name and a literal value and performs - incremental indexing. - """ - if indexbit != INDEX_INCREMENTAL: - prefix = encode_integer(index, 4) - else: - prefix = encode_integer(index, 6) - - prefix[0] |= ord(indexbit) - - if huffman: - value = self.huffman_coder.encode(value) - - value_len = encode_integer(len(value), 7) - - if huffman: - value_len[0] |= 0x80 - - return b"".join([bytes(prefix), bytes(value_len), value]) - - def _encode_table_size_change(self) -> bytes: - """ - Produces the encoded form of all header table size change context - updates. - """ - block = b"" - for size_bytes in self.table_size_changes: - b = encode_integer(size_bytes, 5) - b[0] |= 0x20 - block += bytes(b) - self.table_size_changes = [] - return block - - -class Decoder: - """ - An HPACK decoder object. - - .. versionchanged:: 2.3.0 - Added ``max_header_list_size`` argument. - - :param max_header_list_size: The maximum decompressed size we will allow - for any single header block. This is a protection against DoS attacks - that attempt to force the application to expand a relatively small - amount of data into a really large header list, allowing enormous - amounts of memory to be allocated. - - If this amount of data is exceeded, a `OversizedHeaderListError - ` exception will be raised. At this - point the connection should be shut down, as the HPACK state will no - longer be usable. - - Defaults to 64kB. - :type max_header_list_size: ``int`` - """ - - def __init__(self, max_header_list_size: int = DEFAULT_MAX_HEADER_LIST_SIZE) -> None: - self.header_table = HeaderTable() - - #: The maximum decompressed size we will allow for any single header - #: block. This is a protection against DoS attacks that attempt to - #: force the application to expand a relatively small amount of data - #: into a really large header list, allowing enormous amounts of memory - #: to be allocated. - #: - #: If this amount of data is exceeded, a `OversizedHeaderListError - #: ` exception will be raised. At this - #: point the connection should be shut down, as the HPACK state will no - #: longer be usable. - #: - #: Defaults to 64kB. - #: - #: .. versionadded:: 2.3.0 - self.max_header_list_size = max_header_list_size - - #: Maximum allowed header table size. - #: - #: A HTTP/2 implementation should set this to the most recent value of - #: SETTINGS_HEADER_TABLE_SIZE that it sent *and has received an ACK - #: for*. Once this setting is set, the actual header table size will be - #: checked at the end of each decoding run and whenever it is changed, - #: to confirm that it fits in this size. - self.max_allowed_table_size = self.header_table.maxsize - - @property - def header_table_size(self) -> int: - """ - Controls the size of the HPACK header table. - """ - return self.header_table.maxsize - - @header_table_size.setter - def header_table_size(self, value: int) -> None: - self.header_table.maxsize = value - - def decode(self, data: bytes, raw: bool = False) -> Iterable[HeaderTuple]: - """ - Takes an HPACK-encoded header block and decodes it into a header set. - - :param data: A bytestring representing a complete HPACK-encoded header - block. - :param raw: (optional) Whether to return the headers as tuples of raw - byte strings or to decode them as UTF-8 before returning - them. The default value is False, which returns tuples of - Unicode strings - :returns: A list of two-tuples of ``(name, value)`` representing the - HPACK-encoded headers, in the order they were decoded. - :raises HPACKDecodingError: If an error is encountered while decoding - the header block. - """ - log.debug("Decoding %s", data) - - data_mem = memoryview(data) - headers: list[HeaderTuple] = [] - data_len = len(data) - inflated_size = 0 - current_index = 0 - - while current_index < data_len: - # Work out what kind of header we're decoding. - # If the high bit is 1, it's an indexed field. - current = data[current_index] - indexed = bool(current & 0x80) - - # Otherwise, if the second-highest bit is 1 it's a field that does - # alter the header table. - literal_index = bool(current & 0x40) - - # Otherwise, if the third-highest bit is 1 it's an encoding context - # update. - encoding_update = bool(current & 0x20) - - if indexed: - header, consumed = self._decode_indexed( - data_mem[current_index:], - ) - elif literal_index: - # It's a literal header that does affect the header table. - header, consumed = self._decode_literal_index( - data_mem[current_index:], - ) - elif encoding_update: - # It's an update to the encoding context. These are forbidden - # in a header block after any actual header. - if headers: - msg = "Table size update not at the start of the block" - raise HPACKDecodingError(msg) - consumed = self._update_encoding_context( - data_mem[current_index:], - ) - header = None - else: - # It's a literal header that does not affect the header table. - header, consumed = self._decode_literal_no_index( - data_mem[current_index:], - ) - - if header: - headers.append(header) - inflated_size += table_entry_size(header[0], header[1]) - - if inflated_size > self.max_header_list_size: - msg = f"A header list larger than {self.max_header_list_size} has been received" - raise OversizedHeaderListError(msg) - - current_index += consumed - - # Confirm that the table size is lower than the maximum. We do this - # here to ensure that we catch when the max has been *shrunk* and the - # remote peer hasn't actually done that. - self._assert_valid_table_size() - - try: - return [_unicode_if_needed(h, raw) for h in headers] - except UnicodeDecodeError as err: - msg = "Unable to decode headers as UTF-8" - raise HPACKDecodingError(msg) from err - - def _assert_valid_table_size(self) -> None: - """ - Check that the table size set by the encoder is lower than the maximum - we expect to have. - """ - if self.header_table_size > self.max_allowed_table_size: - msg = "Encoder did not shrink table size to within the max" - raise InvalidTableSizeError(msg) - - def _update_encoding_context(self, data: bytes) -> int: - """ - Handles a byte that updates the encoding context. - """ - # We've been asked to resize the header table. - new_size, consumed = decode_integer(data, 5) - if new_size > self.max_allowed_table_size: - msg = "Encoder exceeded max allowable table size" - raise InvalidTableSizeError(msg) - self.header_table_size = new_size - return consumed - - def _decode_indexed(self, data: bytes) -> tuple[HeaderTuple, int]: - """ - Decodes a header represented using the indexed representation. - """ - index, consumed = decode_integer(data, 7) - header = HeaderTuple(*self.header_table.get_by_index(index)) - log.debug("Decoded %s, consumed %d", header, consumed) - return header, consumed - - def _decode_literal_no_index(self, data: bytes) -> tuple[HeaderTuple, int]: - return self._decode_literal(data, should_index=False) - - def _decode_literal_index(self, data: bytes) -> tuple[HeaderTuple, int]: - return self._decode_literal(data, should_index=True) - - def _decode_literal(self, data: bytes, should_index: bool) -> tuple[HeaderTuple, int]: - """ - Decodes a header represented with a literal. - """ - total_consumed = 0 - - # When should_index is true, if the low six bits of the first byte are - # nonzero, the header name is indexed. - # When should_index is false, if the low four bits of the first byte - # are nonzero the header name is indexed. - if should_index: - indexed_name = data[0] & 0x3F - name_len = 6 - not_indexable = False - else: - high_byte = data[0] - indexed_name = high_byte & 0x0F - name_len = 4 - not_indexable = bool(high_byte & 0x10) - - if indexed_name: - # Indexed header name. - index, consumed = decode_integer(data, name_len) - name = self.header_table.get_by_index(index)[0] - - total_consumed = consumed - length = 0 - else: - # Literal header name. The first byte was consumed, so we need to - # move forward. - data = data[1:] - - length, consumed = decode_integer(data, 7) - name = data[consumed:consumed + length] - if len(name) != length: - msg = "Truncated header block" - raise HPACKDecodingError(msg) - - if data[0] & 0x80: - name = decode_huffman(name) - total_consumed = consumed + length + 1 # Since we moved forward 1. - - data = data[consumed + length:] - - # The header value is definitely length-based. - length, consumed = decode_integer(data, 7) - value = data[consumed:consumed + length] - if len(value) != length: - msg = "Truncated header block" - raise HPACKDecodingError(msg) - - if data[0] & 0x80: - value = decode_huffman(value) - - # Updated the total consumed length. - total_consumed += length + consumed - - # If we have been told never to index the header field, encode that in - # the tuple we use. - header: HeaderTuple - if not_indexable: - header = NeverIndexedHeaderTuple(name, value) - else: - header = HeaderTuple(name, value) - - # If we've been asked to index this, add it to the header table. - if should_index: - self.header_table.add(name, value) - - log.debug( - "Decoded %s, total consumed %d bytes, indexed %s", - header, - total_consumed, - should_index, - ) - - return header, total_consumed diff --git a/serverenv/lib/python3.9/site-packages/hpack/huffman.py b/serverenv/lib/python3.9/site-packages/hpack/huffman.py deleted file mode 100644 index f5b06c5..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/huffman.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -An implementation of a bitwise prefix tree specially built for decoding -Huffman-coded content where we already know the Huffman table. -""" -from __future__ import annotations - - -class HuffmanEncoder: - """ - Encodes a string according to the Huffman encoding table defined in the - HPACK specification. - """ - - def __init__(self, huffman_code_list: list[int], huffman_code_list_lengths: list[int]) -> None: - self.huffman_code_list = huffman_code_list - self.huffman_code_list_lengths = huffman_code_list_lengths - - def encode(self, bytes_to_encode: bytes | None) -> bytes: - """ - Given a string of bytes, encodes them according to the HPACK Huffman - specification. - """ - # If handed the empty string, just immediately return. - if not bytes_to_encode: - return b"" - - final_num = 0 - final_int_len = 0 - - # Turn each byte into its huffman code. These codes aren't necessarily - # octet aligned, so keep track of how far through an octet we are. To - # handle this cleanly, just use a single giant integer. - for byte in bytes_to_encode: - bin_int_len = self.huffman_code_list_lengths[byte] - bin_int = self.huffman_code_list[byte] & ( - 2 ** (bin_int_len + 1) - 1 - ) - final_num <<= bin_int_len - final_num |= bin_int - final_int_len += bin_int_len - - # Pad out to an octet with ones. - bits_to_be_padded = (8 - (final_int_len % 8)) % 8 - final_num <<= bits_to_be_padded - final_num |= (1 << bits_to_be_padded) - 1 - - # Convert the number to hex and strip off the leading '0x' and the - # trailing 'L', if present. - s = hex(final_num)[2:].rstrip("L") - - # If this is odd, prepend a zero. - s = "0" + s if len(s) % 2 != 0 else s - - # This number should have twice as many digits as bytes. If not, we're - # missing some leading zeroes. Work out how many bytes we want and how - # many digits we have, then add the missing zero digits to the front. - total_bytes = (final_int_len + bits_to_be_padded) // 8 - expected_digits = total_bytes * 2 - - if len(s) != expected_digits: - missing_digits = expected_digits - len(s) - s = ("0" * missing_digits) + s - - return bytes.fromhex(s) diff --git a/serverenv/lib/python3.9/site-packages/hpack/huffman_constants.py b/serverenv/lib/python3.9/site-packages/hpack/huffman_constants.py deleted file mode 100644 index 146ee79..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/huffman_constants.py +++ /dev/null @@ -1,285 +0,0 @@ -""" -Defines the constant Huffman table. This takes up an upsetting amount of space, -but c'est la vie. -""" -# flake8: noqa - -REQUEST_CODES = [ - 0x1ff8, - 0x7fffd8, - 0xfffffe2, - 0xfffffe3, - 0xfffffe4, - 0xfffffe5, - 0xfffffe6, - 0xfffffe7, - 0xfffffe8, - 0xffffea, - 0x3ffffffc, - 0xfffffe9, - 0xfffffea, - 0x3ffffffd, - 0xfffffeb, - 0xfffffec, - 0xfffffed, - 0xfffffee, - 0xfffffef, - 0xffffff0, - 0xffffff1, - 0xffffff2, - 0x3ffffffe, - 0xffffff3, - 0xffffff4, - 0xffffff5, - 0xffffff6, - 0xffffff7, - 0xffffff8, - 0xffffff9, - 0xffffffa, - 0xffffffb, - 0x14, - 0x3f8, - 0x3f9, - 0xffa, - 0x1ff9, - 0x15, - 0xf8, - 0x7fa, - 0x3fa, - 0x3fb, - 0xf9, - 0x7fb, - 0xfa, - 0x16, - 0x17, - 0x18, - 0x0, - 0x1, - 0x2, - 0x19, - 0x1a, - 0x1b, - 0x1c, - 0x1d, - 0x1e, - 0x1f, - 0x5c, - 0xfb, - 0x7ffc, - 0x20, - 0xffb, - 0x3fc, - 0x1ffa, - 0x21, - 0x5d, - 0x5e, - 0x5f, - 0x60, - 0x61, - 0x62, - 0x63, - 0x64, - 0x65, - 0x66, - 0x67, - 0x68, - 0x69, - 0x6a, - 0x6b, - 0x6c, - 0x6d, - 0x6e, - 0x6f, - 0x70, - 0x71, - 0x72, - 0xfc, - 0x73, - 0xfd, - 0x1ffb, - 0x7fff0, - 0x1ffc, - 0x3ffc, - 0x22, - 0x7ffd, - 0x3, - 0x23, - 0x4, - 0x24, - 0x5, - 0x25, - 0x26, - 0x27, - 0x6, - 0x74, - 0x75, - 0x28, - 0x29, - 0x2a, - 0x7, - 0x2b, - 0x76, - 0x2c, - 0x8, - 0x9, - 0x2d, - 0x77, - 0x78, - 0x79, - 0x7a, - 0x7b, - 0x7ffe, - 0x7fc, - 0x3ffd, - 0x1ffd, - 0xffffffc, - 0xfffe6, - 0x3fffd2, - 0xfffe7, - 0xfffe8, - 0x3fffd3, - 0x3fffd4, - 0x3fffd5, - 0x7fffd9, - 0x3fffd6, - 0x7fffda, - 0x7fffdb, - 0x7fffdc, - 0x7fffdd, - 0x7fffde, - 0xffffeb, - 0x7fffdf, - 0xffffec, - 0xffffed, - 0x3fffd7, - 0x7fffe0, - 0xffffee, - 0x7fffe1, - 0x7fffe2, - 0x7fffe3, - 0x7fffe4, - 0x1fffdc, - 0x3fffd8, - 0x7fffe5, - 0x3fffd9, - 0x7fffe6, - 0x7fffe7, - 0xffffef, - 0x3fffda, - 0x1fffdd, - 0xfffe9, - 0x3fffdb, - 0x3fffdc, - 0x7fffe8, - 0x7fffe9, - 0x1fffde, - 0x7fffea, - 0x3fffdd, - 0x3fffde, - 0xfffff0, - 0x1fffdf, - 0x3fffdf, - 0x7fffeb, - 0x7fffec, - 0x1fffe0, - 0x1fffe1, - 0x3fffe0, - 0x1fffe2, - 0x7fffed, - 0x3fffe1, - 0x7fffee, - 0x7fffef, - 0xfffea, - 0x3fffe2, - 0x3fffe3, - 0x3fffe4, - 0x7ffff0, - 0x3fffe5, - 0x3fffe6, - 0x7ffff1, - 0x3ffffe0, - 0x3ffffe1, - 0xfffeb, - 0x7fff1, - 0x3fffe7, - 0x7ffff2, - 0x3fffe8, - 0x1ffffec, - 0x3ffffe2, - 0x3ffffe3, - 0x3ffffe4, - 0x7ffffde, - 0x7ffffdf, - 0x3ffffe5, - 0xfffff1, - 0x1ffffed, - 0x7fff2, - 0x1fffe3, - 0x3ffffe6, - 0x7ffffe0, - 0x7ffffe1, - 0x3ffffe7, - 0x7ffffe2, - 0xfffff2, - 0x1fffe4, - 0x1fffe5, - 0x3ffffe8, - 0x3ffffe9, - 0xffffffd, - 0x7ffffe3, - 0x7ffffe4, - 0x7ffffe5, - 0xfffec, - 0xfffff3, - 0xfffed, - 0x1fffe6, - 0x3fffe9, - 0x1fffe7, - 0x1fffe8, - 0x7ffff3, - 0x3fffea, - 0x3fffeb, - 0x1ffffee, - 0x1ffffef, - 0xfffff4, - 0xfffff5, - 0x3ffffea, - 0x7ffff4, - 0x3ffffeb, - 0x7ffffe6, - 0x3ffffec, - 0x3ffffed, - 0x7ffffe7, - 0x7ffffe8, - 0x7ffffe9, - 0x7ffffea, - 0x7ffffeb, - 0xffffffe, - 0x7ffffec, - 0x7ffffed, - 0x7ffffee, - 0x7ffffef, - 0x7fffff0, - 0x3ffffee, - 0x3fffffff, -] - -REQUEST_CODES_LENGTH = [ - 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28, - 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6, - 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10, - 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6, - 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5, - 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28, - 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23, - 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24, - 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23, - 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23, - 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25, - 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27, - 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23, - 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26, - 30, -] diff --git a/serverenv/lib/python3.9/site-packages/hpack/huffman_table.py b/serverenv/lib/python3.9/site-packages/hpack/huffman_table.py deleted file mode 100644 index d6b875a..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/huffman_table.py +++ /dev/null @@ -1,4741 +0,0 @@ -""" -Implementation of a Huffman decoding table for HTTP/2. - -This is essentially a Python port of the work originally done for nghttp2's -Huffman decoding. For this reason, while this file is made available under the -MIT license as is the rest of this module, this file is undoubtedly a -derivative work of the nghttp2 file ``nghttp2_hd_huffman_data.c``, obtained -from https://github.com/tatsuhiro-t/nghttp2/ at commit -d2b55ad1a245e1d1964579fa3fac36ebf3939e72. That work is made available under -the Apache 2.0 license under the following terms: - - Copyright (c) 2013 Tatsuhiro Tsujikawa - - 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. - -The essence of this approach is that it builds a finite state machine out of -4-bit nibbles of Huffman coded data. The input function passes 4 bits worth of -data to the state machine each time, which uses those 4 bits of data along with -the current accumulated state data to process the data given. - -For the sake of efficiency, the in-memory representation of the states, -transitions, and result values of the state machine are represented as a long -list containing three-tuples. This list is enormously long, and viewing it as -an in-memory representation is not very clear, but it is laid out here in a way -that is intended to be *somewhat* more clear. - -Essentially, the list is structured as 256 collections of 16 entries (one for -each nibble) of three-tuples. Each collection is called a "node", and the -zeroth collection is called the "root node". The state machine tracks one -value: the "state" byte. - -For each nibble passed to the state machine, it first multiplies the "state" -byte by 16 and adds the numerical value of the nibble. This number is the index -into the large flat list. - -The three-tuple that is found by looking up that index consists of three -values: - -- a new state value, used for subsequent decoding -- a collection of flags, used to determine whether data is emitted or whether - the state machine is complete. -- the byte value to emit, assuming that emitting a byte is required. - -The flags are consulted, if necessary a byte is emitted, and then the next -nibble is used. This continues until the state machine believes it has -completely Huffman-decoded the data. - -This approach has relatively little indirection, and therefore performs -relatively well, particularly on implementations like PyPy where the cost of -loops at the Python-level is not too expensive. The total number of loop -iterations is 4x the number of bytes passed to the decoder. -""" -from __future__ import annotations - -from .exceptions import HPACKDecodingError - - -# This defines the state machine "class" at the top of the file. The reason we -# do this is to keep the terrifing monster state table at the *bottom* of the -# file so you don't have to actually *look* at the damn thing. -def decode_huffman(huffman_string: bytes | bytearray | None) -> bytes: - """ - Given a bytestring of Huffman-encoded data for HPACK, returns a bytestring - of the decompressed data. - """ - if not huffman_string: - return b"" - - state = 0 - flags = 0 - decoded_bytes = bytearray() - - # Perversely, bytearrays are a lot more convenient across Python 2 and - # Python 3 because they behave *the same way* on both platforms. Given that - # we really do want numerical bytes when we iterate here, let's use a - # bytearray. - huffman_string = bytearray(huffman_string) - - # This loop is unrolled somewhat. Because we use a nibble, not a byte, we - # need to handle each nibble twice. We unroll that: it makes the loop body - # a bit longer, but that's ok. - for input_byte in huffman_string: - index = (state * 16) + (input_byte >> 4) - state, flags, output_byte = HUFFMAN_TABLE[index] - - if flags & HUFFMAN_FAIL: - msg = "Invalid Huffman string" - raise HPACKDecodingError(msg) - - if flags & HUFFMAN_EMIT_SYMBOL: - decoded_bytes.append(output_byte) - - index = (state * 16) + (input_byte & 0x0F) - state, flags, output_byte = HUFFMAN_TABLE[index] - - if flags & HUFFMAN_FAIL: - msg = "Invalid Huffman string" - raise HPACKDecodingError(msg) - - if flags & HUFFMAN_EMIT_SYMBOL: - decoded_bytes.append(output_byte) - - if not (flags & HUFFMAN_COMPLETE): - msg = "Incomplete Huffman string" - raise HPACKDecodingError(msg) - - return bytes(decoded_bytes) - - -# Some decoder flags to control state transitions. -HUFFMAN_COMPLETE = 1 -HUFFMAN_EMIT_SYMBOL = (1 << 1) -HUFFMAN_FAIL = (1 << 2) - -# This is the monster table. Avert your eyes, children. -HUFFMAN_TABLE = [ - # Node 0 (Root Node, never emits symbols.) - (4, 0, 0), - (5, 0, 0), - (7, 0, 0), - (8, 0, 0), - (11, 0, 0), - (12, 0, 0), - (16, 0, 0), - (19, 0, 0), - (25, 0, 0), - (28, 0, 0), - (32, 0, 0), - (35, 0, 0), - (42, 0, 0), - (49, 0, 0), - (57, 0, 0), - (64, HUFFMAN_COMPLETE, 0), - - # Node 1 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - (13, 0, 0), - (14, 0, 0), - (17, 0, 0), - (18, 0, 0), - (20, 0, 0), - (21, 0, 0), - - # Node 2 - (1, HUFFMAN_EMIT_SYMBOL, 48), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (1, HUFFMAN_EMIT_SYMBOL, 49), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - (1, HUFFMAN_EMIT_SYMBOL, 50), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (1, HUFFMAN_EMIT_SYMBOL, 97), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - (1, HUFFMAN_EMIT_SYMBOL, 99), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (1, HUFFMAN_EMIT_SYMBOL, 101), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - (1, HUFFMAN_EMIT_SYMBOL, 105), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (1, HUFFMAN_EMIT_SYMBOL, 111), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - - # Node 3 - (2, HUFFMAN_EMIT_SYMBOL, 48), - (9, HUFFMAN_EMIT_SYMBOL, 48), - (23, HUFFMAN_EMIT_SYMBOL, 48), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (2, HUFFMAN_EMIT_SYMBOL, 49), - (9, HUFFMAN_EMIT_SYMBOL, 49), - (23, HUFFMAN_EMIT_SYMBOL, 49), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - (2, HUFFMAN_EMIT_SYMBOL, 50), - (9, HUFFMAN_EMIT_SYMBOL, 50), - (23, HUFFMAN_EMIT_SYMBOL, 50), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (2, HUFFMAN_EMIT_SYMBOL, 97), - (9, HUFFMAN_EMIT_SYMBOL, 97), - (23, HUFFMAN_EMIT_SYMBOL, 97), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - - # Node 4 - (3, HUFFMAN_EMIT_SYMBOL, 48), - (6, HUFFMAN_EMIT_SYMBOL, 48), - (10, HUFFMAN_EMIT_SYMBOL, 48), - (15, HUFFMAN_EMIT_SYMBOL, 48), - (24, HUFFMAN_EMIT_SYMBOL, 48), - (31, HUFFMAN_EMIT_SYMBOL, 48), - (41, HUFFMAN_EMIT_SYMBOL, 48), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (3, HUFFMAN_EMIT_SYMBOL, 49), - (6, HUFFMAN_EMIT_SYMBOL, 49), - (10, HUFFMAN_EMIT_SYMBOL, 49), - (15, HUFFMAN_EMIT_SYMBOL, 49), - (24, HUFFMAN_EMIT_SYMBOL, 49), - (31, HUFFMAN_EMIT_SYMBOL, 49), - (41, HUFFMAN_EMIT_SYMBOL, 49), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - - # Node 5 - (3, HUFFMAN_EMIT_SYMBOL, 50), - (6, HUFFMAN_EMIT_SYMBOL, 50), - (10, HUFFMAN_EMIT_SYMBOL, 50), - (15, HUFFMAN_EMIT_SYMBOL, 50), - (24, HUFFMAN_EMIT_SYMBOL, 50), - (31, HUFFMAN_EMIT_SYMBOL, 50), - (41, HUFFMAN_EMIT_SYMBOL, 50), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (3, HUFFMAN_EMIT_SYMBOL, 97), - (6, HUFFMAN_EMIT_SYMBOL, 97), - (10, HUFFMAN_EMIT_SYMBOL, 97), - (15, HUFFMAN_EMIT_SYMBOL, 97), - (24, HUFFMAN_EMIT_SYMBOL, 97), - (31, HUFFMAN_EMIT_SYMBOL, 97), - (41, HUFFMAN_EMIT_SYMBOL, 97), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - - # Node 6 - (2, HUFFMAN_EMIT_SYMBOL, 99), - (9, HUFFMAN_EMIT_SYMBOL, 99), - (23, HUFFMAN_EMIT_SYMBOL, 99), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (2, HUFFMAN_EMIT_SYMBOL, 101), - (9, HUFFMAN_EMIT_SYMBOL, 101), - (23, HUFFMAN_EMIT_SYMBOL, 101), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - (2, HUFFMAN_EMIT_SYMBOL, 105), - (9, HUFFMAN_EMIT_SYMBOL, 105), - (23, HUFFMAN_EMIT_SYMBOL, 105), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (2, HUFFMAN_EMIT_SYMBOL, 111), - (9, HUFFMAN_EMIT_SYMBOL, 111), - (23, HUFFMAN_EMIT_SYMBOL, 111), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - - # Node 7 - (3, HUFFMAN_EMIT_SYMBOL, 99), - (6, HUFFMAN_EMIT_SYMBOL, 99), - (10, HUFFMAN_EMIT_SYMBOL, 99), - (15, HUFFMAN_EMIT_SYMBOL, 99), - (24, HUFFMAN_EMIT_SYMBOL, 99), - (31, HUFFMAN_EMIT_SYMBOL, 99), - (41, HUFFMAN_EMIT_SYMBOL, 99), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (3, HUFFMAN_EMIT_SYMBOL, 101), - (6, HUFFMAN_EMIT_SYMBOL, 101), - (10, HUFFMAN_EMIT_SYMBOL, 101), - (15, HUFFMAN_EMIT_SYMBOL, 101), - (24, HUFFMAN_EMIT_SYMBOL, 101), - (31, HUFFMAN_EMIT_SYMBOL, 101), - (41, HUFFMAN_EMIT_SYMBOL, 101), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - - # Node 8 - (3, HUFFMAN_EMIT_SYMBOL, 105), - (6, HUFFMAN_EMIT_SYMBOL, 105), - (10, HUFFMAN_EMIT_SYMBOL, 105), - (15, HUFFMAN_EMIT_SYMBOL, 105), - (24, HUFFMAN_EMIT_SYMBOL, 105), - (31, HUFFMAN_EMIT_SYMBOL, 105), - (41, HUFFMAN_EMIT_SYMBOL, 105), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (3, HUFFMAN_EMIT_SYMBOL, 111), - (6, HUFFMAN_EMIT_SYMBOL, 111), - (10, HUFFMAN_EMIT_SYMBOL, 111), - (15, HUFFMAN_EMIT_SYMBOL, 111), - (24, HUFFMAN_EMIT_SYMBOL, 111), - (31, HUFFMAN_EMIT_SYMBOL, 111), - (41, HUFFMAN_EMIT_SYMBOL, 111), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - - # Node 9 - (1, HUFFMAN_EMIT_SYMBOL, 115), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (1, HUFFMAN_EMIT_SYMBOL, 116), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 10 - (2, HUFFMAN_EMIT_SYMBOL, 115), - (9, HUFFMAN_EMIT_SYMBOL, 115), - (23, HUFFMAN_EMIT_SYMBOL, 115), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (2, HUFFMAN_EMIT_SYMBOL, 116), - (9, HUFFMAN_EMIT_SYMBOL, 116), - (23, HUFFMAN_EMIT_SYMBOL, 116), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - (1, HUFFMAN_EMIT_SYMBOL, 32), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (1, HUFFMAN_EMIT_SYMBOL, 37), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - (1, HUFFMAN_EMIT_SYMBOL, 45), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (1, HUFFMAN_EMIT_SYMBOL, 46), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - - # Node 11 - (3, HUFFMAN_EMIT_SYMBOL, 115), - (6, HUFFMAN_EMIT_SYMBOL, 115), - (10, HUFFMAN_EMIT_SYMBOL, 115), - (15, HUFFMAN_EMIT_SYMBOL, 115), - (24, HUFFMAN_EMIT_SYMBOL, 115), - (31, HUFFMAN_EMIT_SYMBOL, 115), - (41, HUFFMAN_EMIT_SYMBOL, 115), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (3, HUFFMAN_EMIT_SYMBOL, 116), - (6, HUFFMAN_EMIT_SYMBOL, 116), - (10, HUFFMAN_EMIT_SYMBOL, 116), - (15, HUFFMAN_EMIT_SYMBOL, 116), - (24, HUFFMAN_EMIT_SYMBOL, 116), - (31, HUFFMAN_EMIT_SYMBOL, 116), - (41, HUFFMAN_EMIT_SYMBOL, 116), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - - # Node 12 - (2, HUFFMAN_EMIT_SYMBOL, 32), - (9, HUFFMAN_EMIT_SYMBOL, 32), - (23, HUFFMAN_EMIT_SYMBOL, 32), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (2, HUFFMAN_EMIT_SYMBOL, 37), - (9, HUFFMAN_EMIT_SYMBOL, 37), - (23, HUFFMAN_EMIT_SYMBOL, 37), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - (2, HUFFMAN_EMIT_SYMBOL, 45), - (9, HUFFMAN_EMIT_SYMBOL, 45), - (23, HUFFMAN_EMIT_SYMBOL, 45), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (2, HUFFMAN_EMIT_SYMBOL, 46), - (9, HUFFMAN_EMIT_SYMBOL, 46), - (23, HUFFMAN_EMIT_SYMBOL, 46), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - - # Node 13 - (3, HUFFMAN_EMIT_SYMBOL, 32), - (6, HUFFMAN_EMIT_SYMBOL, 32), - (10, HUFFMAN_EMIT_SYMBOL, 32), - (15, HUFFMAN_EMIT_SYMBOL, 32), - (24, HUFFMAN_EMIT_SYMBOL, 32), - (31, HUFFMAN_EMIT_SYMBOL, 32), - (41, HUFFMAN_EMIT_SYMBOL, 32), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (3, HUFFMAN_EMIT_SYMBOL, 37), - (6, HUFFMAN_EMIT_SYMBOL, 37), - (10, HUFFMAN_EMIT_SYMBOL, 37), - (15, HUFFMAN_EMIT_SYMBOL, 37), - (24, HUFFMAN_EMIT_SYMBOL, 37), - (31, HUFFMAN_EMIT_SYMBOL, 37), - (41, HUFFMAN_EMIT_SYMBOL, 37), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - - # Node 14 - (3, HUFFMAN_EMIT_SYMBOL, 45), - (6, HUFFMAN_EMIT_SYMBOL, 45), - (10, HUFFMAN_EMIT_SYMBOL, 45), - (15, HUFFMAN_EMIT_SYMBOL, 45), - (24, HUFFMAN_EMIT_SYMBOL, 45), - (31, HUFFMAN_EMIT_SYMBOL, 45), - (41, HUFFMAN_EMIT_SYMBOL, 45), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (3, HUFFMAN_EMIT_SYMBOL, 46), - (6, HUFFMAN_EMIT_SYMBOL, 46), - (10, HUFFMAN_EMIT_SYMBOL, 46), - (15, HUFFMAN_EMIT_SYMBOL, 46), - (24, HUFFMAN_EMIT_SYMBOL, 46), - (31, HUFFMAN_EMIT_SYMBOL, 46), - (41, HUFFMAN_EMIT_SYMBOL, 46), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - - # Node 15 - (1, HUFFMAN_EMIT_SYMBOL, 47), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (1, HUFFMAN_EMIT_SYMBOL, 51), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - (1, HUFFMAN_EMIT_SYMBOL, 52), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (1, HUFFMAN_EMIT_SYMBOL, 53), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - (1, HUFFMAN_EMIT_SYMBOL, 54), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (1, HUFFMAN_EMIT_SYMBOL, 55), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - (1, HUFFMAN_EMIT_SYMBOL, 56), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (1, HUFFMAN_EMIT_SYMBOL, 57), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 16 - (2, HUFFMAN_EMIT_SYMBOL, 47), - (9, HUFFMAN_EMIT_SYMBOL, 47), - (23, HUFFMAN_EMIT_SYMBOL, 47), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (2, HUFFMAN_EMIT_SYMBOL, 51), - (9, HUFFMAN_EMIT_SYMBOL, 51), - (23, HUFFMAN_EMIT_SYMBOL, 51), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - (2, HUFFMAN_EMIT_SYMBOL, 52), - (9, HUFFMAN_EMIT_SYMBOL, 52), - (23, HUFFMAN_EMIT_SYMBOL, 52), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (2, HUFFMAN_EMIT_SYMBOL, 53), - (9, HUFFMAN_EMIT_SYMBOL, 53), - (23, HUFFMAN_EMIT_SYMBOL, 53), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - - # Node 17 - (3, HUFFMAN_EMIT_SYMBOL, 47), - (6, HUFFMAN_EMIT_SYMBOL, 47), - (10, HUFFMAN_EMIT_SYMBOL, 47), - (15, HUFFMAN_EMIT_SYMBOL, 47), - (24, HUFFMAN_EMIT_SYMBOL, 47), - (31, HUFFMAN_EMIT_SYMBOL, 47), - (41, HUFFMAN_EMIT_SYMBOL, 47), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (3, HUFFMAN_EMIT_SYMBOL, 51), - (6, HUFFMAN_EMIT_SYMBOL, 51), - (10, HUFFMAN_EMIT_SYMBOL, 51), - (15, HUFFMAN_EMIT_SYMBOL, 51), - (24, HUFFMAN_EMIT_SYMBOL, 51), - (31, HUFFMAN_EMIT_SYMBOL, 51), - (41, HUFFMAN_EMIT_SYMBOL, 51), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - - # Node 18 - (3, HUFFMAN_EMIT_SYMBOL, 52), - (6, HUFFMAN_EMIT_SYMBOL, 52), - (10, HUFFMAN_EMIT_SYMBOL, 52), - (15, HUFFMAN_EMIT_SYMBOL, 52), - (24, HUFFMAN_EMIT_SYMBOL, 52), - (31, HUFFMAN_EMIT_SYMBOL, 52), - (41, HUFFMAN_EMIT_SYMBOL, 52), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (3, HUFFMAN_EMIT_SYMBOL, 53), - (6, HUFFMAN_EMIT_SYMBOL, 53), - (10, HUFFMAN_EMIT_SYMBOL, 53), - (15, HUFFMAN_EMIT_SYMBOL, 53), - (24, HUFFMAN_EMIT_SYMBOL, 53), - (31, HUFFMAN_EMIT_SYMBOL, 53), - (41, HUFFMAN_EMIT_SYMBOL, 53), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - - # Node 19 - (2, HUFFMAN_EMIT_SYMBOL, 54), - (9, HUFFMAN_EMIT_SYMBOL, 54), - (23, HUFFMAN_EMIT_SYMBOL, 54), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (2, HUFFMAN_EMIT_SYMBOL, 55), - (9, HUFFMAN_EMIT_SYMBOL, 55), - (23, HUFFMAN_EMIT_SYMBOL, 55), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - (2, HUFFMAN_EMIT_SYMBOL, 56), - (9, HUFFMAN_EMIT_SYMBOL, 56), - (23, HUFFMAN_EMIT_SYMBOL, 56), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (2, HUFFMAN_EMIT_SYMBOL, 57), - (9, HUFFMAN_EMIT_SYMBOL, 57), - (23, HUFFMAN_EMIT_SYMBOL, 57), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 20 - (3, HUFFMAN_EMIT_SYMBOL, 54), - (6, HUFFMAN_EMIT_SYMBOL, 54), - (10, HUFFMAN_EMIT_SYMBOL, 54), - (15, HUFFMAN_EMIT_SYMBOL, 54), - (24, HUFFMAN_EMIT_SYMBOL, 54), - (31, HUFFMAN_EMIT_SYMBOL, 54), - (41, HUFFMAN_EMIT_SYMBOL, 54), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (3, HUFFMAN_EMIT_SYMBOL, 55), - (6, HUFFMAN_EMIT_SYMBOL, 55), - (10, HUFFMAN_EMIT_SYMBOL, 55), - (15, HUFFMAN_EMIT_SYMBOL, 55), - (24, HUFFMAN_EMIT_SYMBOL, 55), - (31, HUFFMAN_EMIT_SYMBOL, 55), - (41, HUFFMAN_EMIT_SYMBOL, 55), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - - # Node 21 - (3, HUFFMAN_EMIT_SYMBOL, 56), - (6, HUFFMAN_EMIT_SYMBOL, 56), - (10, HUFFMAN_EMIT_SYMBOL, 56), - (15, HUFFMAN_EMIT_SYMBOL, 56), - (24, HUFFMAN_EMIT_SYMBOL, 56), - (31, HUFFMAN_EMIT_SYMBOL, 56), - (41, HUFFMAN_EMIT_SYMBOL, 56), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (3, HUFFMAN_EMIT_SYMBOL, 57), - (6, HUFFMAN_EMIT_SYMBOL, 57), - (10, HUFFMAN_EMIT_SYMBOL, 57), - (15, HUFFMAN_EMIT_SYMBOL, 57), - (24, HUFFMAN_EMIT_SYMBOL, 57), - (31, HUFFMAN_EMIT_SYMBOL, 57), - (41, HUFFMAN_EMIT_SYMBOL, 57), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 22 - (26, 0, 0), - (27, 0, 0), - (29, 0, 0), - (30, 0, 0), - (33, 0, 0), - (34, 0, 0), - (36, 0, 0), - (37, 0, 0), - (43, 0, 0), - (46, 0, 0), - (50, 0, 0), - (53, 0, 0), - (58, 0, 0), - (61, 0, 0), - (65, 0, 0), - (68, HUFFMAN_COMPLETE, 0), - - # Node 23 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - (38, 0, 0), - (39, 0, 0), - - # Node 24 - (1, HUFFMAN_EMIT_SYMBOL, 61), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (1, HUFFMAN_EMIT_SYMBOL, 65), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - (1, HUFFMAN_EMIT_SYMBOL, 95), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (1, HUFFMAN_EMIT_SYMBOL, 98), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - (1, HUFFMAN_EMIT_SYMBOL, 100), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (1, HUFFMAN_EMIT_SYMBOL, 102), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - (1, HUFFMAN_EMIT_SYMBOL, 103), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (1, HUFFMAN_EMIT_SYMBOL, 104), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - - # Node 25 - (2, HUFFMAN_EMIT_SYMBOL, 61), - (9, HUFFMAN_EMIT_SYMBOL, 61), - (23, HUFFMAN_EMIT_SYMBOL, 61), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (2, HUFFMAN_EMIT_SYMBOL, 65), - (9, HUFFMAN_EMIT_SYMBOL, 65), - (23, HUFFMAN_EMIT_SYMBOL, 65), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - (2, HUFFMAN_EMIT_SYMBOL, 95), - (9, HUFFMAN_EMIT_SYMBOL, 95), - (23, HUFFMAN_EMIT_SYMBOL, 95), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (2, HUFFMAN_EMIT_SYMBOL, 98), - (9, HUFFMAN_EMIT_SYMBOL, 98), - (23, HUFFMAN_EMIT_SYMBOL, 98), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - - # Node 26 - (3, HUFFMAN_EMIT_SYMBOL, 61), - (6, HUFFMAN_EMIT_SYMBOL, 61), - (10, HUFFMAN_EMIT_SYMBOL, 61), - (15, HUFFMAN_EMIT_SYMBOL, 61), - (24, HUFFMAN_EMIT_SYMBOL, 61), - (31, HUFFMAN_EMIT_SYMBOL, 61), - (41, HUFFMAN_EMIT_SYMBOL, 61), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (3, HUFFMAN_EMIT_SYMBOL, 65), - (6, HUFFMAN_EMIT_SYMBOL, 65), - (10, HUFFMAN_EMIT_SYMBOL, 65), - (15, HUFFMAN_EMIT_SYMBOL, 65), - (24, HUFFMAN_EMIT_SYMBOL, 65), - (31, HUFFMAN_EMIT_SYMBOL, 65), - (41, HUFFMAN_EMIT_SYMBOL, 65), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - - # Node 27 - (3, HUFFMAN_EMIT_SYMBOL, 95), - (6, HUFFMAN_EMIT_SYMBOL, 95), - (10, HUFFMAN_EMIT_SYMBOL, 95), - (15, HUFFMAN_EMIT_SYMBOL, 95), - (24, HUFFMAN_EMIT_SYMBOL, 95), - (31, HUFFMAN_EMIT_SYMBOL, 95), - (41, HUFFMAN_EMIT_SYMBOL, 95), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (3, HUFFMAN_EMIT_SYMBOL, 98), - (6, HUFFMAN_EMIT_SYMBOL, 98), - (10, HUFFMAN_EMIT_SYMBOL, 98), - (15, HUFFMAN_EMIT_SYMBOL, 98), - (24, HUFFMAN_EMIT_SYMBOL, 98), - (31, HUFFMAN_EMIT_SYMBOL, 98), - (41, HUFFMAN_EMIT_SYMBOL, 98), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - - # Node 28 - (2, HUFFMAN_EMIT_SYMBOL, 100), - (9, HUFFMAN_EMIT_SYMBOL, 100), - (23, HUFFMAN_EMIT_SYMBOL, 100), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (2, HUFFMAN_EMIT_SYMBOL, 102), - (9, HUFFMAN_EMIT_SYMBOL, 102), - (23, HUFFMAN_EMIT_SYMBOL, 102), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - (2, HUFFMAN_EMIT_SYMBOL, 103), - (9, HUFFMAN_EMIT_SYMBOL, 103), - (23, HUFFMAN_EMIT_SYMBOL, 103), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (2, HUFFMAN_EMIT_SYMBOL, 104), - (9, HUFFMAN_EMIT_SYMBOL, 104), - (23, HUFFMAN_EMIT_SYMBOL, 104), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - - # Node 29 - (3, HUFFMAN_EMIT_SYMBOL, 100), - (6, HUFFMAN_EMIT_SYMBOL, 100), - (10, HUFFMAN_EMIT_SYMBOL, 100), - (15, HUFFMAN_EMIT_SYMBOL, 100), - (24, HUFFMAN_EMIT_SYMBOL, 100), - (31, HUFFMAN_EMIT_SYMBOL, 100), - (41, HUFFMAN_EMIT_SYMBOL, 100), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (3, HUFFMAN_EMIT_SYMBOL, 102), - (6, HUFFMAN_EMIT_SYMBOL, 102), - (10, HUFFMAN_EMIT_SYMBOL, 102), - (15, HUFFMAN_EMIT_SYMBOL, 102), - (24, HUFFMAN_EMIT_SYMBOL, 102), - (31, HUFFMAN_EMIT_SYMBOL, 102), - (41, HUFFMAN_EMIT_SYMBOL, 102), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - - # Node 30 - (3, HUFFMAN_EMIT_SYMBOL, 103), - (6, HUFFMAN_EMIT_SYMBOL, 103), - (10, HUFFMAN_EMIT_SYMBOL, 103), - (15, HUFFMAN_EMIT_SYMBOL, 103), - (24, HUFFMAN_EMIT_SYMBOL, 103), - (31, HUFFMAN_EMIT_SYMBOL, 103), - (41, HUFFMAN_EMIT_SYMBOL, 103), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (3, HUFFMAN_EMIT_SYMBOL, 104), - (6, HUFFMAN_EMIT_SYMBOL, 104), - (10, HUFFMAN_EMIT_SYMBOL, 104), - (15, HUFFMAN_EMIT_SYMBOL, 104), - (24, HUFFMAN_EMIT_SYMBOL, 104), - (31, HUFFMAN_EMIT_SYMBOL, 104), - (41, HUFFMAN_EMIT_SYMBOL, 104), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - - # Node 31 - (1, HUFFMAN_EMIT_SYMBOL, 108), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (1, HUFFMAN_EMIT_SYMBOL, 109), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - (1, HUFFMAN_EMIT_SYMBOL, 110), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (1, HUFFMAN_EMIT_SYMBOL, 112), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - (1, HUFFMAN_EMIT_SYMBOL, 114), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (1, HUFFMAN_EMIT_SYMBOL, 117), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 32 - (2, HUFFMAN_EMIT_SYMBOL, 108), - (9, HUFFMAN_EMIT_SYMBOL, 108), - (23, HUFFMAN_EMIT_SYMBOL, 108), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (2, HUFFMAN_EMIT_SYMBOL, 109), - (9, HUFFMAN_EMIT_SYMBOL, 109), - (23, HUFFMAN_EMIT_SYMBOL, 109), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - (2, HUFFMAN_EMIT_SYMBOL, 110), - (9, HUFFMAN_EMIT_SYMBOL, 110), - (23, HUFFMAN_EMIT_SYMBOL, 110), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (2, HUFFMAN_EMIT_SYMBOL, 112), - (9, HUFFMAN_EMIT_SYMBOL, 112), - (23, HUFFMAN_EMIT_SYMBOL, 112), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - - # Node 33 - (3, HUFFMAN_EMIT_SYMBOL, 108), - (6, HUFFMAN_EMIT_SYMBOL, 108), - (10, HUFFMAN_EMIT_SYMBOL, 108), - (15, HUFFMAN_EMIT_SYMBOL, 108), - (24, HUFFMAN_EMIT_SYMBOL, 108), - (31, HUFFMAN_EMIT_SYMBOL, 108), - (41, HUFFMAN_EMIT_SYMBOL, 108), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (3, HUFFMAN_EMIT_SYMBOL, 109), - (6, HUFFMAN_EMIT_SYMBOL, 109), - (10, HUFFMAN_EMIT_SYMBOL, 109), - (15, HUFFMAN_EMIT_SYMBOL, 109), - (24, HUFFMAN_EMIT_SYMBOL, 109), - (31, HUFFMAN_EMIT_SYMBOL, 109), - (41, HUFFMAN_EMIT_SYMBOL, 109), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - - # Node 34 - (3, HUFFMAN_EMIT_SYMBOL, 110), - (6, HUFFMAN_EMIT_SYMBOL, 110), - (10, HUFFMAN_EMIT_SYMBOL, 110), - (15, HUFFMAN_EMIT_SYMBOL, 110), - (24, HUFFMAN_EMIT_SYMBOL, 110), - (31, HUFFMAN_EMIT_SYMBOL, 110), - (41, HUFFMAN_EMIT_SYMBOL, 110), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (3, HUFFMAN_EMIT_SYMBOL, 112), - (6, HUFFMAN_EMIT_SYMBOL, 112), - (10, HUFFMAN_EMIT_SYMBOL, 112), - (15, HUFFMAN_EMIT_SYMBOL, 112), - (24, HUFFMAN_EMIT_SYMBOL, 112), - (31, HUFFMAN_EMIT_SYMBOL, 112), - (41, HUFFMAN_EMIT_SYMBOL, 112), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - - # Node 35 - (2, HUFFMAN_EMIT_SYMBOL, 114), - (9, HUFFMAN_EMIT_SYMBOL, 114), - (23, HUFFMAN_EMIT_SYMBOL, 114), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (2, HUFFMAN_EMIT_SYMBOL, 117), - (9, HUFFMAN_EMIT_SYMBOL, 117), - (23, HUFFMAN_EMIT_SYMBOL, 117), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - (1, HUFFMAN_EMIT_SYMBOL, 58), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (1, HUFFMAN_EMIT_SYMBOL, 66), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - (1, HUFFMAN_EMIT_SYMBOL, 67), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (1, HUFFMAN_EMIT_SYMBOL, 68), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 36 - (3, HUFFMAN_EMIT_SYMBOL, 114), - (6, HUFFMAN_EMIT_SYMBOL, 114), - (10, HUFFMAN_EMIT_SYMBOL, 114), - (15, HUFFMAN_EMIT_SYMBOL, 114), - (24, HUFFMAN_EMIT_SYMBOL, 114), - (31, HUFFMAN_EMIT_SYMBOL, 114), - (41, HUFFMAN_EMIT_SYMBOL, 114), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (3, HUFFMAN_EMIT_SYMBOL, 117), - (6, HUFFMAN_EMIT_SYMBOL, 117), - (10, HUFFMAN_EMIT_SYMBOL, 117), - (15, HUFFMAN_EMIT_SYMBOL, 117), - (24, HUFFMAN_EMIT_SYMBOL, 117), - (31, HUFFMAN_EMIT_SYMBOL, 117), - (41, HUFFMAN_EMIT_SYMBOL, 117), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - - # Node 37 - (2, HUFFMAN_EMIT_SYMBOL, 58), - (9, HUFFMAN_EMIT_SYMBOL, 58), - (23, HUFFMAN_EMIT_SYMBOL, 58), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (2, HUFFMAN_EMIT_SYMBOL, 66), - (9, HUFFMAN_EMIT_SYMBOL, 66), - (23, HUFFMAN_EMIT_SYMBOL, 66), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - (2, HUFFMAN_EMIT_SYMBOL, 67), - (9, HUFFMAN_EMIT_SYMBOL, 67), - (23, HUFFMAN_EMIT_SYMBOL, 67), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (2, HUFFMAN_EMIT_SYMBOL, 68), - (9, HUFFMAN_EMIT_SYMBOL, 68), - (23, HUFFMAN_EMIT_SYMBOL, 68), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 38 - (3, HUFFMAN_EMIT_SYMBOL, 58), - (6, HUFFMAN_EMIT_SYMBOL, 58), - (10, HUFFMAN_EMIT_SYMBOL, 58), - (15, HUFFMAN_EMIT_SYMBOL, 58), - (24, HUFFMAN_EMIT_SYMBOL, 58), - (31, HUFFMAN_EMIT_SYMBOL, 58), - (41, HUFFMAN_EMIT_SYMBOL, 58), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (3, HUFFMAN_EMIT_SYMBOL, 66), - (6, HUFFMAN_EMIT_SYMBOL, 66), - (10, HUFFMAN_EMIT_SYMBOL, 66), - (15, HUFFMAN_EMIT_SYMBOL, 66), - (24, HUFFMAN_EMIT_SYMBOL, 66), - (31, HUFFMAN_EMIT_SYMBOL, 66), - (41, HUFFMAN_EMIT_SYMBOL, 66), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - - # Node 39 - (3, HUFFMAN_EMIT_SYMBOL, 67), - (6, HUFFMAN_EMIT_SYMBOL, 67), - (10, HUFFMAN_EMIT_SYMBOL, 67), - (15, HUFFMAN_EMIT_SYMBOL, 67), - (24, HUFFMAN_EMIT_SYMBOL, 67), - (31, HUFFMAN_EMIT_SYMBOL, 67), - (41, HUFFMAN_EMIT_SYMBOL, 67), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (3, HUFFMAN_EMIT_SYMBOL, 68), - (6, HUFFMAN_EMIT_SYMBOL, 68), - (10, HUFFMAN_EMIT_SYMBOL, 68), - (15, HUFFMAN_EMIT_SYMBOL, 68), - (24, HUFFMAN_EMIT_SYMBOL, 68), - (31, HUFFMAN_EMIT_SYMBOL, 68), - (41, HUFFMAN_EMIT_SYMBOL, 68), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 40 - (44, 0, 0), - (45, 0, 0), - (47, 0, 0), - (48, 0, 0), - (51, 0, 0), - (52, 0, 0), - (54, 0, 0), - (55, 0, 0), - (59, 0, 0), - (60, 0, 0), - (62, 0, 0), - (63, 0, 0), - (66, 0, 0), - (67, 0, 0), - (69, 0, 0), - (72, HUFFMAN_COMPLETE, 0), - - # Node 41 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 42 - (1, HUFFMAN_EMIT_SYMBOL, 69), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (1, HUFFMAN_EMIT_SYMBOL, 70), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - (1, HUFFMAN_EMIT_SYMBOL, 71), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (1, HUFFMAN_EMIT_SYMBOL, 72), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - (1, HUFFMAN_EMIT_SYMBOL, 73), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (1, HUFFMAN_EMIT_SYMBOL, 74), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - (1, HUFFMAN_EMIT_SYMBOL, 75), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (1, HUFFMAN_EMIT_SYMBOL, 76), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - - # Node 43 - (2, HUFFMAN_EMIT_SYMBOL, 69), - (9, HUFFMAN_EMIT_SYMBOL, 69), - (23, HUFFMAN_EMIT_SYMBOL, 69), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (2, HUFFMAN_EMIT_SYMBOL, 70), - (9, HUFFMAN_EMIT_SYMBOL, 70), - (23, HUFFMAN_EMIT_SYMBOL, 70), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - (2, HUFFMAN_EMIT_SYMBOL, 71), - (9, HUFFMAN_EMIT_SYMBOL, 71), - (23, HUFFMAN_EMIT_SYMBOL, 71), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (2, HUFFMAN_EMIT_SYMBOL, 72), - (9, HUFFMAN_EMIT_SYMBOL, 72), - (23, HUFFMAN_EMIT_SYMBOL, 72), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - - # Node 44 - (3, HUFFMAN_EMIT_SYMBOL, 69), - (6, HUFFMAN_EMIT_SYMBOL, 69), - (10, HUFFMAN_EMIT_SYMBOL, 69), - (15, HUFFMAN_EMIT_SYMBOL, 69), - (24, HUFFMAN_EMIT_SYMBOL, 69), - (31, HUFFMAN_EMIT_SYMBOL, 69), - (41, HUFFMAN_EMIT_SYMBOL, 69), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (3, HUFFMAN_EMIT_SYMBOL, 70), - (6, HUFFMAN_EMIT_SYMBOL, 70), - (10, HUFFMAN_EMIT_SYMBOL, 70), - (15, HUFFMAN_EMIT_SYMBOL, 70), - (24, HUFFMAN_EMIT_SYMBOL, 70), - (31, HUFFMAN_EMIT_SYMBOL, 70), - (41, HUFFMAN_EMIT_SYMBOL, 70), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - - # Node 45 - (3, HUFFMAN_EMIT_SYMBOL, 71), - (6, HUFFMAN_EMIT_SYMBOL, 71), - (10, HUFFMAN_EMIT_SYMBOL, 71), - (15, HUFFMAN_EMIT_SYMBOL, 71), - (24, HUFFMAN_EMIT_SYMBOL, 71), - (31, HUFFMAN_EMIT_SYMBOL, 71), - (41, HUFFMAN_EMIT_SYMBOL, 71), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (3, HUFFMAN_EMIT_SYMBOL, 72), - (6, HUFFMAN_EMIT_SYMBOL, 72), - (10, HUFFMAN_EMIT_SYMBOL, 72), - (15, HUFFMAN_EMIT_SYMBOL, 72), - (24, HUFFMAN_EMIT_SYMBOL, 72), - (31, HUFFMAN_EMIT_SYMBOL, 72), - (41, HUFFMAN_EMIT_SYMBOL, 72), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - - # Node 46 - (2, HUFFMAN_EMIT_SYMBOL, 73), - (9, HUFFMAN_EMIT_SYMBOL, 73), - (23, HUFFMAN_EMIT_SYMBOL, 73), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (2, HUFFMAN_EMIT_SYMBOL, 74), - (9, HUFFMAN_EMIT_SYMBOL, 74), - (23, HUFFMAN_EMIT_SYMBOL, 74), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - (2, HUFFMAN_EMIT_SYMBOL, 75), - (9, HUFFMAN_EMIT_SYMBOL, 75), - (23, HUFFMAN_EMIT_SYMBOL, 75), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (2, HUFFMAN_EMIT_SYMBOL, 76), - (9, HUFFMAN_EMIT_SYMBOL, 76), - (23, HUFFMAN_EMIT_SYMBOL, 76), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - - # Node 47 - (3, HUFFMAN_EMIT_SYMBOL, 73), - (6, HUFFMAN_EMIT_SYMBOL, 73), - (10, HUFFMAN_EMIT_SYMBOL, 73), - (15, HUFFMAN_EMIT_SYMBOL, 73), - (24, HUFFMAN_EMIT_SYMBOL, 73), - (31, HUFFMAN_EMIT_SYMBOL, 73), - (41, HUFFMAN_EMIT_SYMBOL, 73), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (3, HUFFMAN_EMIT_SYMBOL, 74), - (6, HUFFMAN_EMIT_SYMBOL, 74), - (10, HUFFMAN_EMIT_SYMBOL, 74), - (15, HUFFMAN_EMIT_SYMBOL, 74), - (24, HUFFMAN_EMIT_SYMBOL, 74), - (31, HUFFMAN_EMIT_SYMBOL, 74), - (41, HUFFMAN_EMIT_SYMBOL, 74), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - - # Node 48 - (3, HUFFMAN_EMIT_SYMBOL, 75), - (6, HUFFMAN_EMIT_SYMBOL, 75), - (10, HUFFMAN_EMIT_SYMBOL, 75), - (15, HUFFMAN_EMIT_SYMBOL, 75), - (24, HUFFMAN_EMIT_SYMBOL, 75), - (31, HUFFMAN_EMIT_SYMBOL, 75), - (41, HUFFMAN_EMIT_SYMBOL, 75), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (3, HUFFMAN_EMIT_SYMBOL, 76), - (6, HUFFMAN_EMIT_SYMBOL, 76), - (10, HUFFMAN_EMIT_SYMBOL, 76), - (15, HUFFMAN_EMIT_SYMBOL, 76), - (24, HUFFMAN_EMIT_SYMBOL, 76), - (31, HUFFMAN_EMIT_SYMBOL, 76), - (41, HUFFMAN_EMIT_SYMBOL, 76), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - - # Node 49 - (1, HUFFMAN_EMIT_SYMBOL, 77), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (1, HUFFMAN_EMIT_SYMBOL, 78), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - (1, HUFFMAN_EMIT_SYMBOL, 79), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (1, HUFFMAN_EMIT_SYMBOL, 80), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - (1, HUFFMAN_EMIT_SYMBOL, 81), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (1, HUFFMAN_EMIT_SYMBOL, 82), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - (1, HUFFMAN_EMIT_SYMBOL, 83), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (1, HUFFMAN_EMIT_SYMBOL, 84), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 50 - (2, HUFFMAN_EMIT_SYMBOL, 77), - (9, HUFFMAN_EMIT_SYMBOL, 77), - (23, HUFFMAN_EMIT_SYMBOL, 77), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (2, HUFFMAN_EMIT_SYMBOL, 78), - (9, HUFFMAN_EMIT_SYMBOL, 78), - (23, HUFFMAN_EMIT_SYMBOL, 78), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - (2, HUFFMAN_EMIT_SYMBOL, 79), - (9, HUFFMAN_EMIT_SYMBOL, 79), - (23, HUFFMAN_EMIT_SYMBOL, 79), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (2, HUFFMAN_EMIT_SYMBOL, 80), - (9, HUFFMAN_EMIT_SYMBOL, 80), - (23, HUFFMAN_EMIT_SYMBOL, 80), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - - # Node 51 - (3, HUFFMAN_EMIT_SYMBOL, 77), - (6, HUFFMAN_EMIT_SYMBOL, 77), - (10, HUFFMAN_EMIT_SYMBOL, 77), - (15, HUFFMAN_EMIT_SYMBOL, 77), - (24, HUFFMAN_EMIT_SYMBOL, 77), - (31, HUFFMAN_EMIT_SYMBOL, 77), - (41, HUFFMAN_EMIT_SYMBOL, 77), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (3, HUFFMAN_EMIT_SYMBOL, 78), - (6, HUFFMAN_EMIT_SYMBOL, 78), - (10, HUFFMAN_EMIT_SYMBOL, 78), - (15, HUFFMAN_EMIT_SYMBOL, 78), - (24, HUFFMAN_EMIT_SYMBOL, 78), - (31, HUFFMAN_EMIT_SYMBOL, 78), - (41, HUFFMAN_EMIT_SYMBOL, 78), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - - # Node 52 - (3, HUFFMAN_EMIT_SYMBOL, 79), - (6, HUFFMAN_EMIT_SYMBOL, 79), - (10, HUFFMAN_EMIT_SYMBOL, 79), - (15, HUFFMAN_EMIT_SYMBOL, 79), - (24, HUFFMAN_EMIT_SYMBOL, 79), - (31, HUFFMAN_EMIT_SYMBOL, 79), - (41, HUFFMAN_EMIT_SYMBOL, 79), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (3, HUFFMAN_EMIT_SYMBOL, 80), - (6, HUFFMAN_EMIT_SYMBOL, 80), - (10, HUFFMAN_EMIT_SYMBOL, 80), - (15, HUFFMAN_EMIT_SYMBOL, 80), - (24, HUFFMAN_EMIT_SYMBOL, 80), - (31, HUFFMAN_EMIT_SYMBOL, 80), - (41, HUFFMAN_EMIT_SYMBOL, 80), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - - # Node 53 - (2, HUFFMAN_EMIT_SYMBOL, 81), - (9, HUFFMAN_EMIT_SYMBOL, 81), - (23, HUFFMAN_EMIT_SYMBOL, 81), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (2, HUFFMAN_EMIT_SYMBOL, 82), - (9, HUFFMAN_EMIT_SYMBOL, 82), - (23, HUFFMAN_EMIT_SYMBOL, 82), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - (2, HUFFMAN_EMIT_SYMBOL, 83), - (9, HUFFMAN_EMIT_SYMBOL, 83), - (23, HUFFMAN_EMIT_SYMBOL, 83), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (2, HUFFMAN_EMIT_SYMBOL, 84), - (9, HUFFMAN_EMIT_SYMBOL, 84), - (23, HUFFMAN_EMIT_SYMBOL, 84), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 54 - (3, HUFFMAN_EMIT_SYMBOL, 81), - (6, HUFFMAN_EMIT_SYMBOL, 81), - (10, HUFFMAN_EMIT_SYMBOL, 81), - (15, HUFFMAN_EMIT_SYMBOL, 81), - (24, HUFFMAN_EMIT_SYMBOL, 81), - (31, HUFFMAN_EMIT_SYMBOL, 81), - (41, HUFFMAN_EMIT_SYMBOL, 81), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (3, HUFFMAN_EMIT_SYMBOL, 82), - (6, HUFFMAN_EMIT_SYMBOL, 82), - (10, HUFFMAN_EMIT_SYMBOL, 82), - (15, HUFFMAN_EMIT_SYMBOL, 82), - (24, HUFFMAN_EMIT_SYMBOL, 82), - (31, HUFFMAN_EMIT_SYMBOL, 82), - (41, HUFFMAN_EMIT_SYMBOL, 82), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - - # Node 55 - (3, HUFFMAN_EMIT_SYMBOL, 83), - (6, HUFFMAN_EMIT_SYMBOL, 83), - (10, HUFFMAN_EMIT_SYMBOL, 83), - (15, HUFFMAN_EMIT_SYMBOL, 83), - (24, HUFFMAN_EMIT_SYMBOL, 83), - (31, HUFFMAN_EMIT_SYMBOL, 83), - (41, HUFFMAN_EMIT_SYMBOL, 83), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (3, HUFFMAN_EMIT_SYMBOL, 84), - (6, HUFFMAN_EMIT_SYMBOL, 84), - (10, HUFFMAN_EMIT_SYMBOL, 84), - (15, HUFFMAN_EMIT_SYMBOL, 84), - (24, HUFFMAN_EMIT_SYMBOL, 84), - (31, HUFFMAN_EMIT_SYMBOL, 84), - (41, HUFFMAN_EMIT_SYMBOL, 84), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 56 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - (70, 0, 0), - (71, 0, 0), - (73, 0, 0), - (74, HUFFMAN_COMPLETE, 0), - - # Node 57 - (1, HUFFMAN_EMIT_SYMBOL, 85), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (1, HUFFMAN_EMIT_SYMBOL, 86), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - (1, HUFFMAN_EMIT_SYMBOL, 87), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (1, HUFFMAN_EMIT_SYMBOL, 89), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - (1, HUFFMAN_EMIT_SYMBOL, 106), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (1, HUFFMAN_EMIT_SYMBOL, 107), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - (1, HUFFMAN_EMIT_SYMBOL, 113), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (1, HUFFMAN_EMIT_SYMBOL, 118), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - - # Node 58 - (2, HUFFMAN_EMIT_SYMBOL, 85), - (9, HUFFMAN_EMIT_SYMBOL, 85), - (23, HUFFMAN_EMIT_SYMBOL, 85), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (2, HUFFMAN_EMIT_SYMBOL, 86), - (9, HUFFMAN_EMIT_SYMBOL, 86), - (23, HUFFMAN_EMIT_SYMBOL, 86), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - (2, HUFFMAN_EMIT_SYMBOL, 87), - (9, HUFFMAN_EMIT_SYMBOL, 87), - (23, HUFFMAN_EMIT_SYMBOL, 87), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (2, HUFFMAN_EMIT_SYMBOL, 89), - (9, HUFFMAN_EMIT_SYMBOL, 89), - (23, HUFFMAN_EMIT_SYMBOL, 89), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - - # Node 59 - (3, HUFFMAN_EMIT_SYMBOL, 85), - (6, HUFFMAN_EMIT_SYMBOL, 85), - (10, HUFFMAN_EMIT_SYMBOL, 85), - (15, HUFFMAN_EMIT_SYMBOL, 85), - (24, HUFFMAN_EMIT_SYMBOL, 85), - (31, HUFFMAN_EMIT_SYMBOL, 85), - (41, HUFFMAN_EMIT_SYMBOL, 85), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (3, HUFFMAN_EMIT_SYMBOL, 86), - (6, HUFFMAN_EMIT_SYMBOL, 86), - (10, HUFFMAN_EMIT_SYMBOL, 86), - (15, HUFFMAN_EMIT_SYMBOL, 86), - (24, HUFFMAN_EMIT_SYMBOL, 86), - (31, HUFFMAN_EMIT_SYMBOL, 86), - (41, HUFFMAN_EMIT_SYMBOL, 86), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - - # Node 60 - (3, HUFFMAN_EMIT_SYMBOL, 87), - (6, HUFFMAN_EMIT_SYMBOL, 87), - (10, HUFFMAN_EMIT_SYMBOL, 87), - (15, HUFFMAN_EMIT_SYMBOL, 87), - (24, HUFFMAN_EMIT_SYMBOL, 87), - (31, HUFFMAN_EMIT_SYMBOL, 87), - (41, HUFFMAN_EMIT_SYMBOL, 87), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (3, HUFFMAN_EMIT_SYMBOL, 89), - (6, HUFFMAN_EMIT_SYMBOL, 89), - (10, HUFFMAN_EMIT_SYMBOL, 89), - (15, HUFFMAN_EMIT_SYMBOL, 89), - (24, HUFFMAN_EMIT_SYMBOL, 89), - (31, HUFFMAN_EMIT_SYMBOL, 89), - (41, HUFFMAN_EMIT_SYMBOL, 89), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - - # Node 61 - (2, HUFFMAN_EMIT_SYMBOL, 106), - (9, HUFFMAN_EMIT_SYMBOL, 106), - (23, HUFFMAN_EMIT_SYMBOL, 106), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (2, HUFFMAN_EMIT_SYMBOL, 107), - (9, HUFFMAN_EMIT_SYMBOL, 107), - (23, HUFFMAN_EMIT_SYMBOL, 107), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - (2, HUFFMAN_EMIT_SYMBOL, 113), - (9, HUFFMAN_EMIT_SYMBOL, 113), - (23, HUFFMAN_EMIT_SYMBOL, 113), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (2, HUFFMAN_EMIT_SYMBOL, 118), - (9, HUFFMAN_EMIT_SYMBOL, 118), - (23, HUFFMAN_EMIT_SYMBOL, 118), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - - # Node 62 - (3, HUFFMAN_EMIT_SYMBOL, 106), - (6, HUFFMAN_EMIT_SYMBOL, 106), - (10, HUFFMAN_EMIT_SYMBOL, 106), - (15, HUFFMAN_EMIT_SYMBOL, 106), - (24, HUFFMAN_EMIT_SYMBOL, 106), - (31, HUFFMAN_EMIT_SYMBOL, 106), - (41, HUFFMAN_EMIT_SYMBOL, 106), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (3, HUFFMAN_EMIT_SYMBOL, 107), - (6, HUFFMAN_EMIT_SYMBOL, 107), - (10, HUFFMAN_EMIT_SYMBOL, 107), - (15, HUFFMAN_EMIT_SYMBOL, 107), - (24, HUFFMAN_EMIT_SYMBOL, 107), - (31, HUFFMAN_EMIT_SYMBOL, 107), - (41, HUFFMAN_EMIT_SYMBOL, 107), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - - # Node 63 - (3, HUFFMAN_EMIT_SYMBOL, 113), - (6, HUFFMAN_EMIT_SYMBOL, 113), - (10, HUFFMAN_EMIT_SYMBOL, 113), - (15, HUFFMAN_EMIT_SYMBOL, 113), - (24, HUFFMAN_EMIT_SYMBOL, 113), - (31, HUFFMAN_EMIT_SYMBOL, 113), - (41, HUFFMAN_EMIT_SYMBOL, 113), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (3, HUFFMAN_EMIT_SYMBOL, 118), - (6, HUFFMAN_EMIT_SYMBOL, 118), - (10, HUFFMAN_EMIT_SYMBOL, 118), - (15, HUFFMAN_EMIT_SYMBOL, 118), - (24, HUFFMAN_EMIT_SYMBOL, 118), - (31, HUFFMAN_EMIT_SYMBOL, 118), - (41, HUFFMAN_EMIT_SYMBOL, 118), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - - # Node 64 - (1, HUFFMAN_EMIT_SYMBOL, 119), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (1, HUFFMAN_EMIT_SYMBOL, 120), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - (1, HUFFMAN_EMIT_SYMBOL, 121), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (1, HUFFMAN_EMIT_SYMBOL, 122), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - (75, 0, 0), - (78, 0, 0), - - # Node 65 - (2, HUFFMAN_EMIT_SYMBOL, 119), - (9, HUFFMAN_EMIT_SYMBOL, 119), - (23, HUFFMAN_EMIT_SYMBOL, 119), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (2, HUFFMAN_EMIT_SYMBOL, 120), - (9, HUFFMAN_EMIT_SYMBOL, 120), - (23, HUFFMAN_EMIT_SYMBOL, 120), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - (2, HUFFMAN_EMIT_SYMBOL, 121), - (9, HUFFMAN_EMIT_SYMBOL, 121), - (23, HUFFMAN_EMIT_SYMBOL, 121), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (2, HUFFMAN_EMIT_SYMBOL, 122), - (9, HUFFMAN_EMIT_SYMBOL, 122), - (23, HUFFMAN_EMIT_SYMBOL, 122), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - - # Node 66 - (3, HUFFMAN_EMIT_SYMBOL, 119), - (6, HUFFMAN_EMIT_SYMBOL, 119), - (10, HUFFMAN_EMIT_SYMBOL, 119), - (15, HUFFMAN_EMIT_SYMBOL, 119), - (24, HUFFMAN_EMIT_SYMBOL, 119), - (31, HUFFMAN_EMIT_SYMBOL, 119), - (41, HUFFMAN_EMIT_SYMBOL, 119), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (3, HUFFMAN_EMIT_SYMBOL, 120), - (6, HUFFMAN_EMIT_SYMBOL, 120), - (10, HUFFMAN_EMIT_SYMBOL, 120), - (15, HUFFMAN_EMIT_SYMBOL, 120), - (24, HUFFMAN_EMIT_SYMBOL, 120), - (31, HUFFMAN_EMIT_SYMBOL, 120), - (41, HUFFMAN_EMIT_SYMBOL, 120), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - - # Node 67 - (3, HUFFMAN_EMIT_SYMBOL, 121), - (6, HUFFMAN_EMIT_SYMBOL, 121), - (10, HUFFMAN_EMIT_SYMBOL, 121), - (15, HUFFMAN_EMIT_SYMBOL, 121), - (24, HUFFMAN_EMIT_SYMBOL, 121), - (31, HUFFMAN_EMIT_SYMBOL, 121), - (41, HUFFMAN_EMIT_SYMBOL, 121), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (3, HUFFMAN_EMIT_SYMBOL, 122), - (6, HUFFMAN_EMIT_SYMBOL, 122), - (10, HUFFMAN_EMIT_SYMBOL, 122), - (15, HUFFMAN_EMIT_SYMBOL, 122), - (24, HUFFMAN_EMIT_SYMBOL, 122), - (31, HUFFMAN_EMIT_SYMBOL, 122), - (41, HUFFMAN_EMIT_SYMBOL, 122), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - - # Node 68 - (1, HUFFMAN_EMIT_SYMBOL, 38), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (1, HUFFMAN_EMIT_SYMBOL, 42), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - (1, HUFFMAN_EMIT_SYMBOL, 44), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (1, HUFFMAN_EMIT_SYMBOL, 59), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - (1, HUFFMAN_EMIT_SYMBOL, 88), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (1, HUFFMAN_EMIT_SYMBOL, 90), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - (76, 0, 0), - (77, 0, 0), - (79, 0, 0), - (81, 0, 0), - - # Node 69 - (2, HUFFMAN_EMIT_SYMBOL, 38), - (9, HUFFMAN_EMIT_SYMBOL, 38), - (23, HUFFMAN_EMIT_SYMBOL, 38), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (2, HUFFMAN_EMIT_SYMBOL, 42), - (9, HUFFMAN_EMIT_SYMBOL, 42), - (23, HUFFMAN_EMIT_SYMBOL, 42), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - (2, HUFFMAN_EMIT_SYMBOL, 44), - (9, HUFFMAN_EMIT_SYMBOL, 44), - (23, HUFFMAN_EMIT_SYMBOL, 44), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (2, HUFFMAN_EMIT_SYMBOL, 59), - (9, HUFFMAN_EMIT_SYMBOL, 59), - (23, HUFFMAN_EMIT_SYMBOL, 59), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - - # Node 70 - (3, HUFFMAN_EMIT_SYMBOL, 38), - (6, HUFFMAN_EMIT_SYMBOL, 38), - (10, HUFFMAN_EMIT_SYMBOL, 38), - (15, HUFFMAN_EMIT_SYMBOL, 38), - (24, HUFFMAN_EMIT_SYMBOL, 38), - (31, HUFFMAN_EMIT_SYMBOL, 38), - (41, HUFFMAN_EMIT_SYMBOL, 38), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (3, HUFFMAN_EMIT_SYMBOL, 42), - (6, HUFFMAN_EMIT_SYMBOL, 42), - (10, HUFFMAN_EMIT_SYMBOL, 42), - (15, HUFFMAN_EMIT_SYMBOL, 42), - (24, HUFFMAN_EMIT_SYMBOL, 42), - (31, HUFFMAN_EMIT_SYMBOL, 42), - (41, HUFFMAN_EMIT_SYMBOL, 42), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - - # Node 71 - (3, HUFFMAN_EMIT_SYMBOL, 44), - (6, HUFFMAN_EMIT_SYMBOL, 44), - (10, HUFFMAN_EMIT_SYMBOL, 44), - (15, HUFFMAN_EMIT_SYMBOL, 44), - (24, HUFFMAN_EMIT_SYMBOL, 44), - (31, HUFFMAN_EMIT_SYMBOL, 44), - (41, HUFFMAN_EMIT_SYMBOL, 44), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (3, HUFFMAN_EMIT_SYMBOL, 59), - (6, HUFFMAN_EMIT_SYMBOL, 59), - (10, HUFFMAN_EMIT_SYMBOL, 59), - (15, HUFFMAN_EMIT_SYMBOL, 59), - (24, HUFFMAN_EMIT_SYMBOL, 59), - (31, HUFFMAN_EMIT_SYMBOL, 59), - (41, HUFFMAN_EMIT_SYMBOL, 59), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - - # Node 72 - (2, HUFFMAN_EMIT_SYMBOL, 88), - (9, HUFFMAN_EMIT_SYMBOL, 88), - (23, HUFFMAN_EMIT_SYMBOL, 88), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (2, HUFFMAN_EMIT_SYMBOL, 90), - (9, HUFFMAN_EMIT_SYMBOL, 90), - (23, HUFFMAN_EMIT_SYMBOL, 90), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (80, 0, 0), - (82, 0, 0), - (84, 0, 0), - - # Node 73 - (3, HUFFMAN_EMIT_SYMBOL, 88), - (6, HUFFMAN_EMIT_SYMBOL, 88), - (10, HUFFMAN_EMIT_SYMBOL, 88), - (15, HUFFMAN_EMIT_SYMBOL, 88), - (24, HUFFMAN_EMIT_SYMBOL, 88), - (31, HUFFMAN_EMIT_SYMBOL, 88), - (41, HUFFMAN_EMIT_SYMBOL, 88), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (3, HUFFMAN_EMIT_SYMBOL, 90), - (6, HUFFMAN_EMIT_SYMBOL, 90), - (10, HUFFMAN_EMIT_SYMBOL, 90), - (15, HUFFMAN_EMIT_SYMBOL, 90), - (24, HUFFMAN_EMIT_SYMBOL, 90), - (31, HUFFMAN_EMIT_SYMBOL, 90), - (41, HUFFMAN_EMIT_SYMBOL, 90), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - - # Node 74 - (1, HUFFMAN_EMIT_SYMBOL, 33), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (1, HUFFMAN_EMIT_SYMBOL, 34), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - (1, HUFFMAN_EMIT_SYMBOL, 40), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (1, HUFFMAN_EMIT_SYMBOL, 41), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - (1, HUFFMAN_EMIT_SYMBOL, 63), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (83, 0, 0), - (85, 0, 0), - (88, 0, 0), - - # Node 75 - (2, HUFFMAN_EMIT_SYMBOL, 33), - (9, HUFFMAN_EMIT_SYMBOL, 33), - (23, HUFFMAN_EMIT_SYMBOL, 33), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (2, HUFFMAN_EMIT_SYMBOL, 34), - (9, HUFFMAN_EMIT_SYMBOL, 34), - (23, HUFFMAN_EMIT_SYMBOL, 34), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - (2, HUFFMAN_EMIT_SYMBOL, 40), - (9, HUFFMAN_EMIT_SYMBOL, 40), - (23, HUFFMAN_EMIT_SYMBOL, 40), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (2, HUFFMAN_EMIT_SYMBOL, 41), - (9, HUFFMAN_EMIT_SYMBOL, 41), - (23, HUFFMAN_EMIT_SYMBOL, 41), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - - # Node 76 - (3, HUFFMAN_EMIT_SYMBOL, 33), - (6, HUFFMAN_EMIT_SYMBOL, 33), - (10, HUFFMAN_EMIT_SYMBOL, 33), - (15, HUFFMAN_EMIT_SYMBOL, 33), - (24, HUFFMAN_EMIT_SYMBOL, 33), - (31, HUFFMAN_EMIT_SYMBOL, 33), - (41, HUFFMAN_EMIT_SYMBOL, 33), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (3, HUFFMAN_EMIT_SYMBOL, 34), - (6, HUFFMAN_EMIT_SYMBOL, 34), - (10, HUFFMAN_EMIT_SYMBOL, 34), - (15, HUFFMAN_EMIT_SYMBOL, 34), - (24, HUFFMAN_EMIT_SYMBOL, 34), - (31, HUFFMAN_EMIT_SYMBOL, 34), - (41, HUFFMAN_EMIT_SYMBOL, 34), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - - # Node 77 - (3, HUFFMAN_EMIT_SYMBOL, 40), - (6, HUFFMAN_EMIT_SYMBOL, 40), - (10, HUFFMAN_EMIT_SYMBOL, 40), - (15, HUFFMAN_EMIT_SYMBOL, 40), - (24, HUFFMAN_EMIT_SYMBOL, 40), - (31, HUFFMAN_EMIT_SYMBOL, 40), - (41, HUFFMAN_EMIT_SYMBOL, 40), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (3, HUFFMAN_EMIT_SYMBOL, 41), - (6, HUFFMAN_EMIT_SYMBOL, 41), - (10, HUFFMAN_EMIT_SYMBOL, 41), - (15, HUFFMAN_EMIT_SYMBOL, 41), - (24, HUFFMAN_EMIT_SYMBOL, 41), - (31, HUFFMAN_EMIT_SYMBOL, 41), - (41, HUFFMAN_EMIT_SYMBOL, 41), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - - # Node 78 - (2, HUFFMAN_EMIT_SYMBOL, 63), - (9, HUFFMAN_EMIT_SYMBOL, 63), - (23, HUFFMAN_EMIT_SYMBOL, 63), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (1, HUFFMAN_EMIT_SYMBOL, 39), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (1, HUFFMAN_EMIT_SYMBOL, 43), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - (1, HUFFMAN_EMIT_SYMBOL, 124), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - (86, 0, 0), - (87, 0, 0), - (89, 0, 0), - (90, 0, 0), - - # Node 79 - (3, HUFFMAN_EMIT_SYMBOL, 63), - (6, HUFFMAN_EMIT_SYMBOL, 63), - (10, HUFFMAN_EMIT_SYMBOL, 63), - (15, HUFFMAN_EMIT_SYMBOL, 63), - (24, HUFFMAN_EMIT_SYMBOL, 63), - (31, HUFFMAN_EMIT_SYMBOL, 63), - (41, HUFFMAN_EMIT_SYMBOL, 63), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (2, HUFFMAN_EMIT_SYMBOL, 39), - (9, HUFFMAN_EMIT_SYMBOL, 39), - (23, HUFFMAN_EMIT_SYMBOL, 39), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (2, HUFFMAN_EMIT_SYMBOL, 43), - (9, HUFFMAN_EMIT_SYMBOL, 43), - (23, HUFFMAN_EMIT_SYMBOL, 43), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - - # Node 80 - (3, HUFFMAN_EMIT_SYMBOL, 39), - (6, HUFFMAN_EMIT_SYMBOL, 39), - (10, HUFFMAN_EMIT_SYMBOL, 39), - (15, HUFFMAN_EMIT_SYMBOL, 39), - (24, HUFFMAN_EMIT_SYMBOL, 39), - (31, HUFFMAN_EMIT_SYMBOL, 39), - (41, HUFFMAN_EMIT_SYMBOL, 39), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (3, HUFFMAN_EMIT_SYMBOL, 43), - (6, HUFFMAN_EMIT_SYMBOL, 43), - (10, HUFFMAN_EMIT_SYMBOL, 43), - (15, HUFFMAN_EMIT_SYMBOL, 43), - (24, HUFFMAN_EMIT_SYMBOL, 43), - (31, HUFFMAN_EMIT_SYMBOL, 43), - (41, HUFFMAN_EMIT_SYMBOL, 43), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - - # Node 81 - (2, HUFFMAN_EMIT_SYMBOL, 124), - (9, HUFFMAN_EMIT_SYMBOL, 124), - (23, HUFFMAN_EMIT_SYMBOL, 124), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (1, HUFFMAN_EMIT_SYMBOL, 35), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (1, HUFFMAN_EMIT_SYMBOL, 62), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - (91, 0, 0), - (92, 0, 0), - - # Node 82 - (3, HUFFMAN_EMIT_SYMBOL, 124), - (6, HUFFMAN_EMIT_SYMBOL, 124), - (10, HUFFMAN_EMIT_SYMBOL, 124), - (15, HUFFMAN_EMIT_SYMBOL, 124), - (24, HUFFMAN_EMIT_SYMBOL, 124), - (31, HUFFMAN_EMIT_SYMBOL, 124), - (41, HUFFMAN_EMIT_SYMBOL, 124), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (2, HUFFMAN_EMIT_SYMBOL, 35), - (9, HUFFMAN_EMIT_SYMBOL, 35), - (23, HUFFMAN_EMIT_SYMBOL, 35), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (2, HUFFMAN_EMIT_SYMBOL, 62), - (9, HUFFMAN_EMIT_SYMBOL, 62), - (23, HUFFMAN_EMIT_SYMBOL, 62), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - - # Node 83 - (3, HUFFMAN_EMIT_SYMBOL, 35), - (6, HUFFMAN_EMIT_SYMBOL, 35), - (10, HUFFMAN_EMIT_SYMBOL, 35), - (15, HUFFMAN_EMIT_SYMBOL, 35), - (24, HUFFMAN_EMIT_SYMBOL, 35), - (31, HUFFMAN_EMIT_SYMBOL, 35), - (41, HUFFMAN_EMIT_SYMBOL, 35), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (3, HUFFMAN_EMIT_SYMBOL, 62), - (6, HUFFMAN_EMIT_SYMBOL, 62), - (10, HUFFMAN_EMIT_SYMBOL, 62), - (15, HUFFMAN_EMIT_SYMBOL, 62), - (24, HUFFMAN_EMIT_SYMBOL, 62), - (31, HUFFMAN_EMIT_SYMBOL, 62), - (41, HUFFMAN_EMIT_SYMBOL, 62), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - - # Node 84 - (1, HUFFMAN_EMIT_SYMBOL, 0), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (1, HUFFMAN_EMIT_SYMBOL, 36), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - (1, HUFFMAN_EMIT_SYMBOL, 64), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (1, HUFFMAN_EMIT_SYMBOL, 91), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - (1, HUFFMAN_EMIT_SYMBOL, 93), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (1, HUFFMAN_EMIT_SYMBOL, 126), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - (93, 0, 0), - (94, 0, 0), - - # Node 85 - (2, HUFFMAN_EMIT_SYMBOL, 0), - (9, HUFFMAN_EMIT_SYMBOL, 0), - (23, HUFFMAN_EMIT_SYMBOL, 0), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (2, HUFFMAN_EMIT_SYMBOL, 36), - (9, HUFFMAN_EMIT_SYMBOL, 36), - (23, HUFFMAN_EMIT_SYMBOL, 36), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - (2, HUFFMAN_EMIT_SYMBOL, 64), - (9, HUFFMAN_EMIT_SYMBOL, 64), - (23, HUFFMAN_EMIT_SYMBOL, 64), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (2, HUFFMAN_EMIT_SYMBOL, 91), - (9, HUFFMAN_EMIT_SYMBOL, 91), - (23, HUFFMAN_EMIT_SYMBOL, 91), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - - # Node 86 - (3, HUFFMAN_EMIT_SYMBOL, 0), - (6, HUFFMAN_EMIT_SYMBOL, 0), - (10, HUFFMAN_EMIT_SYMBOL, 0), - (15, HUFFMAN_EMIT_SYMBOL, 0), - (24, HUFFMAN_EMIT_SYMBOL, 0), - (31, HUFFMAN_EMIT_SYMBOL, 0), - (41, HUFFMAN_EMIT_SYMBOL, 0), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (3, HUFFMAN_EMIT_SYMBOL, 36), - (6, HUFFMAN_EMIT_SYMBOL, 36), - (10, HUFFMAN_EMIT_SYMBOL, 36), - (15, HUFFMAN_EMIT_SYMBOL, 36), - (24, HUFFMAN_EMIT_SYMBOL, 36), - (31, HUFFMAN_EMIT_SYMBOL, 36), - (41, HUFFMAN_EMIT_SYMBOL, 36), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - - # Node 87 - (3, HUFFMAN_EMIT_SYMBOL, 64), - (6, HUFFMAN_EMIT_SYMBOL, 64), - (10, HUFFMAN_EMIT_SYMBOL, 64), - (15, HUFFMAN_EMIT_SYMBOL, 64), - (24, HUFFMAN_EMIT_SYMBOL, 64), - (31, HUFFMAN_EMIT_SYMBOL, 64), - (41, HUFFMAN_EMIT_SYMBOL, 64), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (3, HUFFMAN_EMIT_SYMBOL, 91), - (6, HUFFMAN_EMIT_SYMBOL, 91), - (10, HUFFMAN_EMIT_SYMBOL, 91), - (15, HUFFMAN_EMIT_SYMBOL, 91), - (24, HUFFMAN_EMIT_SYMBOL, 91), - (31, HUFFMAN_EMIT_SYMBOL, 91), - (41, HUFFMAN_EMIT_SYMBOL, 91), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - - # Node 88 - (2, HUFFMAN_EMIT_SYMBOL, 93), - (9, HUFFMAN_EMIT_SYMBOL, 93), - (23, HUFFMAN_EMIT_SYMBOL, 93), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (2, HUFFMAN_EMIT_SYMBOL, 126), - (9, HUFFMAN_EMIT_SYMBOL, 126), - (23, HUFFMAN_EMIT_SYMBOL, 126), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - (1, HUFFMAN_EMIT_SYMBOL, 94), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (1, HUFFMAN_EMIT_SYMBOL, 125), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (95, 0, 0), - - # Node 89 - (3, HUFFMAN_EMIT_SYMBOL, 93), - (6, HUFFMAN_EMIT_SYMBOL, 93), - (10, HUFFMAN_EMIT_SYMBOL, 93), - (15, HUFFMAN_EMIT_SYMBOL, 93), - (24, HUFFMAN_EMIT_SYMBOL, 93), - (31, HUFFMAN_EMIT_SYMBOL, 93), - (41, HUFFMAN_EMIT_SYMBOL, 93), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (3, HUFFMAN_EMIT_SYMBOL, 126), - (6, HUFFMAN_EMIT_SYMBOL, 126), - (10, HUFFMAN_EMIT_SYMBOL, 126), - (15, HUFFMAN_EMIT_SYMBOL, 126), - (24, HUFFMAN_EMIT_SYMBOL, 126), - (31, HUFFMAN_EMIT_SYMBOL, 126), - (41, HUFFMAN_EMIT_SYMBOL, 126), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - - # Node 90 - (2, HUFFMAN_EMIT_SYMBOL, 94), - (9, HUFFMAN_EMIT_SYMBOL, 94), - (23, HUFFMAN_EMIT_SYMBOL, 94), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (2, HUFFMAN_EMIT_SYMBOL, 125), - (9, HUFFMAN_EMIT_SYMBOL, 125), - (23, HUFFMAN_EMIT_SYMBOL, 125), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - (1, HUFFMAN_EMIT_SYMBOL, 60), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (1, HUFFMAN_EMIT_SYMBOL, 96), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - (1, HUFFMAN_EMIT_SYMBOL, 123), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (96, 0, 0), - (110, 0, 0), - - # Node 91 - (3, HUFFMAN_EMIT_SYMBOL, 94), - (6, HUFFMAN_EMIT_SYMBOL, 94), - (10, HUFFMAN_EMIT_SYMBOL, 94), - (15, HUFFMAN_EMIT_SYMBOL, 94), - (24, HUFFMAN_EMIT_SYMBOL, 94), - (31, HUFFMAN_EMIT_SYMBOL, 94), - (41, HUFFMAN_EMIT_SYMBOL, 94), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (3, HUFFMAN_EMIT_SYMBOL, 125), - (6, HUFFMAN_EMIT_SYMBOL, 125), - (10, HUFFMAN_EMIT_SYMBOL, 125), - (15, HUFFMAN_EMIT_SYMBOL, 125), - (24, HUFFMAN_EMIT_SYMBOL, 125), - (31, HUFFMAN_EMIT_SYMBOL, 125), - (41, HUFFMAN_EMIT_SYMBOL, 125), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - - # Node 92 - (2, HUFFMAN_EMIT_SYMBOL, 60), - (9, HUFFMAN_EMIT_SYMBOL, 60), - (23, HUFFMAN_EMIT_SYMBOL, 60), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (2, HUFFMAN_EMIT_SYMBOL, 96), - (9, HUFFMAN_EMIT_SYMBOL, 96), - (23, HUFFMAN_EMIT_SYMBOL, 96), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - (2, HUFFMAN_EMIT_SYMBOL, 123), - (9, HUFFMAN_EMIT_SYMBOL, 123), - (23, HUFFMAN_EMIT_SYMBOL, 123), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (97, 0, 0), - (101, 0, 0), - (111, 0, 0), - (133, 0, 0), - - # Node 93 - (3, HUFFMAN_EMIT_SYMBOL, 60), - (6, HUFFMAN_EMIT_SYMBOL, 60), - (10, HUFFMAN_EMIT_SYMBOL, 60), - (15, HUFFMAN_EMIT_SYMBOL, 60), - (24, HUFFMAN_EMIT_SYMBOL, 60), - (31, HUFFMAN_EMIT_SYMBOL, 60), - (41, HUFFMAN_EMIT_SYMBOL, 60), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (3, HUFFMAN_EMIT_SYMBOL, 96), - (6, HUFFMAN_EMIT_SYMBOL, 96), - (10, HUFFMAN_EMIT_SYMBOL, 96), - (15, HUFFMAN_EMIT_SYMBOL, 96), - (24, HUFFMAN_EMIT_SYMBOL, 96), - (31, HUFFMAN_EMIT_SYMBOL, 96), - (41, HUFFMAN_EMIT_SYMBOL, 96), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - - # Node 94 - (3, HUFFMAN_EMIT_SYMBOL, 123), - (6, HUFFMAN_EMIT_SYMBOL, 123), - (10, HUFFMAN_EMIT_SYMBOL, 123), - (15, HUFFMAN_EMIT_SYMBOL, 123), - (24, HUFFMAN_EMIT_SYMBOL, 123), - (31, HUFFMAN_EMIT_SYMBOL, 123), - (41, HUFFMAN_EMIT_SYMBOL, 123), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (98, 0, 0), - (99, 0, 0), - (102, 0, 0), - (105, 0, 0), - (112, 0, 0), - (119, 0, 0), - (134, 0, 0), - (153, 0, 0), - - # Node 95 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (100, 0, 0), - (103, 0, 0), - (104, 0, 0), - (106, 0, 0), - (107, 0, 0), - (113, 0, 0), - (116, 0, 0), - (120, 0, 0), - (126, 0, 0), - (135, 0, 0), - (142, 0, 0), - (154, 0, 0), - (169, 0, 0), - - # Node 96 - (1, HUFFMAN_EMIT_SYMBOL, 92), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (1, HUFFMAN_EMIT_SYMBOL, 195), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - (1, HUFFMAN_EMIT_SYMBOL, 208), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - (108, 0, 0), - (109, 0, 0), - - # Node 97 - (2, HUFFMAN_EMIT_SYMBOL, 92), - (9, HUFFMAN_EMIT_SYMBOL, 92), - (23, HUFFMAN_EMIT_SYMBOL, 92), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (2, HUFFMAN_EMIT_SYMBOL, 195), - (9, HUFFMAN_EMIT_SYMBOL, 195), - (23, HUFFMAN_EMIT_SYMBOL, 195), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - (2, HUFFMAN_EMIT_SYMBOL, 208), - (9, HUFFMAN_EMIT_SYMBOL, 208), - (23, HUFFMAN_EMIT_SYMBOL, 208), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (1, HUFFMAN_EMIT_SYMBOL, 128), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (1, HUFFMAN_EMIT_SYMBOL, 130), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - - # Node 98 - (3, HUFFMAN_EMIT_SYMBOL, 92), - (6, HUFFMAN_EMIT_SYMBOL, 92), - (10, HUFFMAN_EMIT_SYMBOL, 92), - (15, HUFFMAN_EMIT_SYMBOL, 92), - (24, HUFFMAN_EMIT_SYMBOL, 92), - (31, HUFFMAN_EMIT_SYMBOL, 92), - (41, HUFFMAN_EMIT_SYMBOL, 92), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (3, HUFFMAN_EMIT_SYMBOL, 195), - (6, HUFFMAN_EMIT_SYMBOL, 195), - (10, HUFFMAN_EMIT_SYMBOL, 195), - (15, HUFFMAN_EMIT_SYMBOL, 195), - (24, HUFFMAN_EMIT_SYMBOL, 195), - (31, HUFFMAN_EMIT_SYMBOL, 195), - (41, HUFFMAN_EMIT_SYMBOL, 195), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - - # Node 99 - (3, HUFFMAN_EMIT_SYMBOL, 208), - (6, HUFFMAN_EMIT_SYMBOL, 208), - (10, HUFFMAN_EMIT_SYMBOL, 208), - (15, HUFFMAN_EMIT_SYMBOL, 208), - (24, HUFFMAN_EMIT_SYMBOL, 208), - (31, HUFFMAN_EMIT_SYMBOL, 208), - (41, HUFFMAN_EMIT_SYMBOL, 208), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (2, HUFFMAN_EMIT_SYMBOL, 128), - (9, HUFFMAN_EMIT_SYMBOL, 128), - (23, HUFFMAN_EMIT_SYMBOL, 128), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (2, HUFFMAN_EMIT_SYMBOL, 130), - (9, HUFFMAN_EMIT_SYMBOL, 130), - (23, HUFFMAN_EMIT_SYMBOL, 130), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - - # Node 100 - (3, HUFFMAN_EMIT_SYMBOL, 128), - (6, HUFFMAN_EMIT_SYMBOL, 128), - (10, HUFFMAN_EMIT_SYMBOL, 128), - (15, HUFFMAN_EMIT_SYMBOL, 128), - (24, HUFFMAN_EMIT_SYMBOL, 128), - (31, HUFFMAN_EMIT_SYMBOL, 128), - (41, HUFFMAN_EMIT_SYMBOL, 128), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (3, HUFFMAN_EMIT_SYMBOL, 130), - (6, HUFFMAN_EMIT_SYMBOL, 130), - (10, HUFFMAN_EMIT_SYMBOL, 130), - (15, HUFFMAN_EMIT_SYMBOL, 130), - (24, HUFFMAN_EMIT_SYMBOL, 130), - (31, HUFFMAN_EMIT_SYMBOL, 130), - (41, HUFFMAN_EMIT_SYMBOL, 130), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - - # Node 101 - (1, HUFFMAN_EMIT_SYMBOL, 131), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (1, HUFFMAN_EMIT_SYMBOL, 162), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - (1, HUFFMAN_EMIT_SYMBOL, 184), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (1, HUFFMAN_EMIT_SYMBOL, 194), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - (1, HUFFMAN_EMIT_SYMBOL, 224), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (1, HUFFMAN_EMIT_SYMBOL, 226), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 102 - (2, HUFFMAN_EMIT_SYMBOL, 131), - (9, HUFFMAN_EMIT_SYMBOL, 131), - (23, HUFFMAN_EMIT_SYMBOL, 131), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (2, HUFFMAN_EMIT_SYMBOL, 162), - (9, HUFFMAN_EMIT_SYMBOL, 162), - (23, HUFFMAN_EMIT_SYMBOL, 162), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - (2, HUFFMAN_EMIT_SYMBOL, 184), - (9, HUFFMAN_EMIT_SYMBOL, 184), - (23, HUFFMAN_EMIT_SYMBOL, 184), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (2, HUFFMAN_EMIT_SYMBOL, 194), - (9, HUFFMAN_EMIT_SYMBOL, 194), - (23, HUFFMAN_EMIT_SYMBOL, 194), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - - # Node 103 - (3, HUFFMAN_EMIT_SYMBOL, 131), - (6, HUFFMAN_EMIT_SYMBOL, 131), - (10, HUFFMAN_EMIT_SYMBOL, 131), - (15, HUFFMAN_EMIT_SYMBOL, 131), - (24, HUFFMAN_EMIT_SYMBOL, 131), - (31, HUFFMAN_EMIT_SYMBOL, 131), - (41, HUFFMAN_EMIT_SYMBOL, 131), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (3, HUFFMAN_EMIT_SYMBOL, 162), - (6, HUFFMAN_EMIT_SYMBOL, 162), - (10, HUFFMAN_EMIT_SYMBOL, 162), - (15, HUFFMAN_EMIT_SYMBOL, 162), - (24, HUFFMAN_EMIT_SYMBOL, 162), - (31, HUFFMAN_EMIT_SYMBOL, 162), - (41, HUFFMAN_EMIT_SYMBOL, 162), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - - # Node 104 - (3, HUFFMAN_EMIT_SYMBOL, 184), - (6, HUFFMAN_EMIT_SYMBOL, 184), - (10, HUFFMAN_EMIT_SYMBOL, 184), - (15, HUFFMAN_EMIT_SYMBOL, 184), - (24, HUFFMAN_EMIT_SYMBOL, 184), - (31, HUFFMAN_EMIT_SYMBOL, 184), - (41, HUFFMAN_EMIT_SYMBOL, 184), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (3, HUFFMAN_EMIT_SYMBOL, 194), - (6, HUFFMAN_EMIT_SYMBOL, 194), - (10, HUFFMAN_EMIT_SYMBOL, 194), - (15, HUFFMAN_EMIT_SYMBOL, 194), - (24, HUFFMAN_EMIT_SYMBOL, 194), - (31, HUFFMAN_EMIT_SYMBOL, 194), - (41, HUFFMAN_EMIT_SYMBOL, 194), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - - # Node 105 - (2, HUFFMAN_EMIT_SYMBOL, 224), - (9, HUFFMAN_EMIT_SYMBOL, 224), - (23, HUFFMAN_EMIT_SYMBOL, 224), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (2, HUFFMAN_EMIT_SYMBOL, 226), - (9, HUFFMAN_EMIT_SYMBOL, 226), - (23, HUFFMAN_EMIT_SYMBOL, 226), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - (1, HUFFMAN_EMIT_SYMBOL, 153), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (1, HUFFMAN_EMIT_SYMBOL, 161), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - (1, HUFFMAN_EMIT_SYMBOL, 167), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (1, HUFFMAN_EMIT_SYMBOL, 172), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 106 - (3, HUFFMAN_EMIT_SYMBOL, 224), - (6, HUFFMAN_EMIT_SYMBOL, 224), - (10, HUFFMAN_EMIT_SYMBOL, 224), - (15, HUFFMAN_EMIT_SYMBOL, 224), - (24, HUFFMAN_EMIT_SYMBOL, 224), - (31, HUFFMAN_EMIT_SYMBOL, 224), - (41, HUFFMAN_EMIT_SYMBOL, 224), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (3, HUFFMAN_EMIT_SYMBOL, 226), - (6, HUFFMAN_EMIT_SYMBOL, 226), - (10, HUFFMAN_EMIT_SYMBOL, 226), - (15, HUFFMAN_EMIT_SYMBOL, 226), - (24, HUFFMAN_EMIT_SYMBOL, 226), - (31, HUFFMAN_EMIT_SYMBOL, 226), - (41, HUFFMAN_EMIT_SYMBOL, 226), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - - # Node 107 - (2, HUFFMAN_EMIT_SYMBOL, 153), - (9, HUFFMAN_EMIT_SYMBOL, 153), - (23, HUFFMAN_EMIT_SYMBOL, 153), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (2, HUFFMAN_EMIT_SYMBOL, 161), - (9, HUFFMAN_EMIT_SYMBOL, 161), - (23, HUFFMAN_EMIT_SYMBOL, 161), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - (2, HUFFMAN_EMIT_SYMBOL, 167), - (9, HUFFMAN_EMIT_SYMBOL, 167), - (23, HUFFMAN_EMIT_SYMBOL, 167), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (2, HUFFMAN_EMIT_SYMBOL, 172), - (9, HUFFMAN_EMIT_SYMBOL, 172), - (23, HUFFMAN_EMIT_SYMBOL, 172), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 108 - (3, HUFFMAN_EMIT_SYMBOL, 153), - (6, HUFFMAN_EMIT_SYMBOL, 153), - (10, HUFFMAN_EMIT_SYMBOL, 153), - (15, HUFFMAN_EMIT_SYMBOL, 153), - (24, HUFFMAN_EMIT_SYMBOL, 153), - (31, HUFFMAN_EMIT_SYMBOL, 153), - (41, HUFFMAN_EMIT_SYMBOL, 153), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (3, HUFFMAN_EMIT_SYMBOL, 161), - (6, HUFFMAN_EMIT_SYMBOL, 161), - (10, HUFFMAN_EMIT_SYMBOL, 161), - (15, HUFFMAN_EMIT_SYMBOL, 161), - (24, HUFFMAN_EMIT_SYMBOL, 161), - (31, HUFFMAN_EMIT_SYMBOL, 161), - (41, HUFFMAN_EMIT_SYMBOL, 161), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - - # Node 109 - (3, HUFFMAN_EMIT_SYMBOL, 167), - (6, HUFFMAN_EMIT_SYMBOL, 167), - (10, HUFFMAN_EMIT_SYMBOL, 167), - (15, HUFFMAN_EMIT_SYMBOL, 167), - (24, HUFFMAN_EMIT_SYMBOL, 167), - (31, HUFFMAN_EMIT_SYMBOL, 167), - (41, HUFFMAN_EMIT_SYMBOL, 167), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (3, HUFFMAN_EMIT_SYMBOL, 172), - (6, HUFFMAN_EMIT_SYMBOL, 172), - (10, HUFFMAN_EMIT_SYMBOL, 172), - (15, HUFFMAN_EMIT_SYMBOL, 172), - (24, HUFFMAN_EMIT_SYMBOL, 172), - (31, HUFFMAN_EMIT_SYMBOL, 172), - (41, HUFFMAN_EMIT_SYMBOL, 172), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 110 - (114, 0, 0), - (115, 0, 0), - (117, 0, 0), - (118, 0, 0), - (121, 0, 0), - (123, 0, 0), - (127, 0, 0), - (130, 0, 0), - (136, 0, 0), - (139, 0, 0), - (143, 0, 0), - (146, 0, 0), - (155, 0, 0), - (162, 0, 0), - (170, 0, 0), - (180, 0, 0), - - # Node 111 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (122, 0, 0), - (124, 0, 0), - (125, 0, 0), - (128, 0, 0), - (129, 0, 0), - (131, 0, 0), - (132, 0, 0), - - # Node 112 - (1, HUFFMAN_EMIT_SYMBOL, 176), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (1, HUFFMAN_EMIT_SYMBOL, 177), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - (1, HUFFMAN_EMIT_SYMBOL, 179), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (1, HUFFMAN_EMIT_SYMBOL, 209), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - (1, HUFFMAN_EMIT_SYMBOL, 216), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (1, HUFFMAN_EMIT_SYMBOL, 217), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - (1, HUFFMAN_EMIT_SYMBOL, 227), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (1, HUFFMAN_EMIT_SYMBOL, 229), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - - # Node 113 - (2, HUFFMAN_EMIT_SYMBOL, 176), - (9, HUFFMAN_EMIT_SYMBOL, 176), - (23, HUFFMAN_EMIT_SYMBOL, 176), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (2, HUFFMAN_EMIT_SYMBOL, 177), - (9, HUFFMAN_EMIT_SYMBOL, 177), - (23, HUFFMAN_EMIT_SYMBOL, 177), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - (2, HUFFMAN_EMIT_SYMBOL, 179), - (9, HUFFMAN_EMIT_SYMBOL, 179), - (23, HUFFMAN_EMIT_SYMBOL, 179), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (2, HUFFMAN_EMIT_SYMBOL, 209), - (9, HUFFMAN_EMIT_SYMBOL, 209), - (23, HUFFMAN_EMIT_SYMBOL, 209), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - - # Node 114 - (3, HUFFMAN_EMIT_SYMBOL, 176), - (6, HUFFMAN_EMIT_SYMBOL, 176), - (10, HUFFMAN_EMIT_SYMBOL, 176), - (15, HUFFMAN_EMIT_SYMBOL, 176), - (24, HUFFMAN_EMIT_SYMBOL, 176), - (31, HUFFMAN_EMIT_SYMBOL, 176), - (41, HUFFMAN_EMIT_SYMBOL, 176), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (3, HUFFMAN_EMIT_SYMBOL, 177), - (6, HUFFMAN_EMIT_SYMBOL, 177), - (10, HUFFMAN_EMIT_SYMBOL, 177), - (15, HUFFMAN_EMIT_SYMBOL, 177), - (24, HUFFMAN_EMIT_SYMBOL, 177), - (31, HUFFMAN_EMIT_SYMBOL, 177), - (41, HUFFMAN_EMIT_SYMBOL, 177), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - - # Node 115 - (3, HUFFMAN_EMIT_SYMBOL, 179), - (6, HUFFMAN_EMIT_SYMBOL, 179), - (10, HUFFMAN_EMIT_SYMBOL, 179), - (15, HUFFMAN_EMIT_SYMBOL, 179), - (24, HUFFMAN_EMIT_SYMBOL, 179), - (31, HUFFMAN_EMIT_SYMBOL, 179), - (41, HUFFMAN_EMIT_SYMBOL, 179), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (3, HUFFMAN_EMIT_SYMBOL, 209), - (6, HUFFMAN_EMIT_SYMBOL, 209), - (10, HUFFMAN_EMIT_SYMBOL, 209), - (15, HUFFMAN_EMIT_SYMBOL, 209), - (24, HUFFMAN_EMIT_SYMBOL, 209), - (31, HUFFMAN_EMIT_SYMBOL, 209), - (41, HUFFMAN_EMIT_SYMBOL, 209), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - - # Node 116 - (2, HUFFMAN_EMIT_SYMBOL, 216), - (9, HUFFMAN_EMIT_SYMBOL, 216), - (23, HUFFMAN_EMIT_SYMBOL, 216), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (2, HUFFMAN_EMIT_SYMBOL, 217), - (9, HUFFMAN_EMIT_SYMBOL, 217), - (23, HUFFMAN_EMIT_SYMBOL, 217), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - (2, HUFFMAN_EMIT_SYMBOL, 227), - (9, HUFFMAN_EMIT_SYMBOL, 227), - (23, HUFFMAN_EMIT_SYMBOL, 227), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (2, HUFFMAN_EMIT_SYMBOL, 229), - (9, HUFFMAN_EMIT_SYMBOL, 229), - (23, HUFFMAN_EMIT_SYMBOL, 229), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - - # Node 117 - (3, HUFFMAN_EMIT_SYMBOL, 216), - (6, HUFFMAN_EMIT_SYMBOL, 216), - (10, HUFFMAN_EMIT_SYMBOL, 216), - (15, HUFFMAN_EMIT_SYMBOL, 216), - (24, HUFFMAN_EMIT_SYMBOL, 216), - (31, HUFFMAN_EMIT_SYMBOL, 216), - (41, HUFFMAN_EMIT_SYMBOL, 216), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (3, HUFFMAN_EMIT_SYMBOL, 217), - (6, HUFFMAN_EMIT_SYMBOL, 217), - (10, HUFFMAN_EMIT_SYMBOL, 217), - (15, HUFFMAN_EMIT_SYMBOL, 217), - (24, HUFFMAN_EMIT_SYMBOL, 217), - (31, HUFFMAN_EMIT_SYMBOL, 217), - (41, HUFFMAN_EMIT_SYMBOL, 217), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - - # Node 118 - (3, HUFFMAN_EMIT_SYMBOL, 227), - (6, HUFFMAN_EMIT_SYMBOL, 227), - (10, HUFFMAN_EMIT_SYMBOL, 227), - (15, HUFFMAN_EMIT_SYMBOL, 227), - (24, HUFFMAN_EMIT_SYMBOL, 227), - (31, HUFFMAN_EMIT_SYMBOL, 227), - (41, HUFFMAN_EMIT_SYMBOL, 227), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (3, HUFFMAN_EMIT_SYMBOL, 229), - (6, HUFFMAN_EMIT_SYMBOL, 229), - (10, HUFFMAN_EMIT_SYMBOL, 229), - (15, HUFFMAN_EMIT_SYMBOL, 229), - (24, HUFFMAN_EMIT_SYMBOL, 229), - (31, HUFFMAN_EMIT_SYMBOL, 229), - (41, HUFFMAN_EMIT_SYMBOL, 229), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - - # Node 119 - (1, HUFFMAN_EMIT_SYMBOL, 230), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 120 - (2, HUFFMAN_EMIT_SYMBOL, 230), - (9, HUFFMAN_EMIT_SYMBOL, 230), - (23, HUFFMAN_EMIT_SYMBOL, 230), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (1, HUFFMAN_EMIT_SYMBOL, 129), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (1, HUFFMAN_EMIT_SYMBOL, 132), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - (1, HUFFMAN_EMIT_SYMBOL, 133), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (1, HUFFMAN_EMIT_SYMBOL, 134), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - (1, HUFFMAN_EMIT_SYMBOL, 136), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (1, HUFFMAN_EMIT_SYMBOL, 146), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - - # Node 121 - (3, HUFFMAN_EMIT_SYMBOL, 230), - (6, HUFFMAN_EMIT_SYMBOL, 230), - (10, HUFFMAN_EMIT_SYMBOL, 230), - (15, HUFFMAN_EMIT_SYMBOL, 230), - (24, HUFFMAN_EMIT_SYMBOL, 230), - (31, HUFFMAN_EMIT_SYMBOL, 230), - (41, HUFFMAN_EMIT_SYMBOL, 230), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (2, HUFFMAN_EMIT_SYMBOL, 129), - (9, HUFFMAN_EMIT_SYMBOL, 129), - (23, HUFFMAN_EMIT_SYMBOL, 129), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (2, HUFFMAN_EMIT_SYMBOL, 132), - (9, HUFFMAN_EMIT_SYMBOL, 132), - (23, HUFFMAN_EMIT_SYMBOL, 132), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - - # Node 122 - (3, HUFFMAN_EMIT_SYMBOL, 129), - (6, HUFFMAN_EMIT_SYMBOL, 129), - (10, HUFFMAN_EMIT_SYMBOL, 129), - (15, HUFFMAN_EMIT_SYMBOL, 129), - (24, HUFFMAN_EMIT_SYMBOL, 129), - (31, HUFFMAN_EMIT_SYMBOL, 129), - (41, HUFFMAN_EMIT_SYMBOL, 129), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (3, HUFFMAN_EMIT_SYMBOL, 132), - (6, HUFFMAN_EMIT_SYMBOL, 132), - (10, HUFFMAN_EMIT_SYMBOL, 132), - (15, HUFFMAN_EMIT_SYMBOL, 132), - (24, HUFFMAN_EMIT_SYMBOL, 132), - (31, HUFFMAN_EMIT_SYMBOL, 132), - (41, HUFFMAN_EMIT_SYMBOL, 132), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - - # Node 123 - (2, HUFFMAN_EMIT_SYMBOL, 133), - (9, HUFFMAN_EMIT_SYMBOL, 133), - (23, HUFFMAN_EMIT_SYMBOL, 133), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (2, HUFFMAN_EMIT_SYMBOL, 134), - (9, HUFFMAN_EMIT_SYMBOL, 134), - (23, HUFFMAN_EMIT_SYMBOL, 134), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - (2, HUFFMAN_EMIT_SYMBOL, 136), - (9, HUFFMAN_EMIT_SYMBOL, 136), - (23, HUFFMAN_EMIT_SYMBOL, 136), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (2, HUFFMAN_EMIT_SYMBOL, 146), - (9, HUFFMAN_EMIT_SYMBOL, 146), - (23, HUFFMAN_EMIT_SYMBOL, 146), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - - # Node 124 - (3, HUFFMAN_EMIT_SYMBOL, 133), - (6, HUFFMAN_EMIT_SYMBOL, 133), - (10, HUFFMAN_EMIT_SYMBOL, 133), - (15, HUFFMAN_EMIT_SYMBOL, 133), - (24, HUFFMAN_EMIT_SYMBOL, 133), - (31, HUFFMAN_EMIT_SYMBOL, 133), - (41, HUFFMAN_EMIT_SYMBOL, 133), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (3, HUFFMAN_EMIT_SYMBOL, 134), - (6, HUFFMAN_EMIT_SYMBOL, 134), - (10, HUFFMAN_EMIT_SYMBOL, 134), - (15, HUFFMAN_EMIT_SYMBOL, 134), - (24, HUFFMAN_EMIT_SYMBOL, 134), - (31, HUFFMAN_EMIT_SYMBOL, 134), - (41, HUFFMAN_EMIT_SYMBOL, 134), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - - # Node 125 - (3, HUFFMAN_EMIT_SYMBOL, 136), - (6, HUFFMAN_EMIT_SYMBOL, 136), - (10, HUFFMAN_EMIT_SYMBOL, 136), - (15, HUFFMAN_EMIT_SYMBOL, 136), - (24, HUFFMAN_EMIT_SYMBOL, 136), - (31, HUFFMAN_EMIT_SYMBOL, 136), - (41, HUFFMAN_EMIT_SYMBOL, 136), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (3, HUFFMAN_EMIT_SYMBOL, 146), - (6, HUFFMAN_EMIT_SYMBOL, 146), - (10, HUFFMAN_EMIT_SYMBOL, 146), - (15, HUFFMAN_EMIT_SYMBOL, 146), - (24, HUFFMAN_EMIT_SYMBOL, 146), - (31, HUFFMAN_EMIT_SYMBOL, 146), - (41, HUFFMAN_EMIT_SYMBOL, 146), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - - # Node 126 - (1, HUFFMAN_EMIT_SYMBOL, 154), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (1, HUFFMAN_EMIT_SYMBOL, 156), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - (1, HUFFMAN_EMIT_SYMBOL, 160), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (1, HUFFMAN_EMIT_SYMBOL, 163), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - (1, HUFFMAN_EMIT_SYMBOL, 164), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (1, HUFFMAN_EMIT_SYMBOL, 169), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - (1, HUFFMAN_EMIT_SYMBOL, 170), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (1, HUFFMAN_EMIT_SYMBOL, 173), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 127 - (2, HUFFMAN_EMIT_SYMBOL, 154), - (9, HUFFMAN_EMIT_SYMBOL, 154), - (23, HUFFMAN_EMIT_SYMBOL, 154), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (2, HUFFMAN_EMIT_SYMBOL, 156), - (9, HUFFMAN_EMIT_SYMBOL, 156), - (23, HUFFMAN_EMIT_SYMBOL, 156), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - (2, HUFFMAN_EMIT_SYMBOL, 160), - (9, HUFFMAN_EMIT_SYMBOL, 160), - (23, HUFFMAN_EMIT_SYMBOL, 160), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (2, HUFFMAN_EMIT_SYMBOL, 163), - (9, HUFFMAN_EMIT_SYMBOL, 163), - (23, HUFFMAN_EMIT_SYMBOL, 163), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - - # Node 128 - (3, HUFFMAN_EMIT_SYMBOL, 154), - (6, HUFFMAN_EMIT_SYMBOL, 154), - (10, HUFFMAN_EMIT_SYMBOL, 154), - (15, HUFFMAN_EMIT_SYMBOL, 154), - (24, HUFFMAN_EMIT_SYMBOL, 154), - (31, HUFFMAN_EMIT_SYMBOL, 154), - (41, HUFFMAN_EMIT_SYMBOL, 154), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (3, HUFFMAN_EMIT_SYMBOL, 156), - (6, HUFFMAN_EMIT_SYMBOL, 156), - (10, HUFFMAN_EMIT_SYMBOL, 156), - (15, HUFFMAN_EMIT_SYMBOL, 156), - (24, HUFFMAN_EMIT_SYMBOL, 156), - (31, HUFFMAN_EMIT_SYMBOL, 156), - (41, HUFFMAN_EMIT_SYMBOL, 156), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - - # Node 129 - (3, HUFFMAN_EMIT_SYMBOL, 160), - (6, HUFFMAN_EMIT_SYMBOL, 160), - (10, HUFFMAN_EMIT_SYMBOL, 160), - (15, HUFFMAN_EMIT_SYMBOL, 160), - (24, HUFFMAN_EMIT_SYMBOL, 160), - (31, HUFFMAN_EMIT_SYMBOL, 160), - (41, HUFFMAN_EMIT_SYMBOL, 160), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (3, HUFFMAN_EMIT_SYMBOL, 163), - (6, HUFFMAN_EMIT_SYMBOL, 163), - (10, HUFFMAN_EMIT_SYMBOL, 163), - (15, HUFFMAN_EMIT_SYMBOL, 163), - (24, HUFFMAN_EMIT_SYMBOL, 163), - (31, HUFFMAN_EMIT_SYMBOL, 163), - (41, HUFFMAN_EMIT_SYMBOL, 163), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - - # Node 130 - (2, HUFFMAN_EMIT_SYMBOL, 164), - (9, HUFFMAN_EMIT_SYMBOL, 164), - (23, HUFFMAN_EMIT_SYMBOL, 164), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (2, HUFFMAN_EMIT_SYMBOL, 169), - (9, HUFFMAN_EMIT_SYMBOL, 169), - (23, HUFFMAN_EMIT_SYMBOL, 169), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - (2, HUFFMAN_EMIT_SYMBOL, 170), - (9, HUFFMAN_EMIT_SYMBOL, 170), - (23, HUFFMAN_EMIT_SYMBOL, 170), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (2, HUFFMAN_EMIT_SYMBOL, 173), - (9, HUFFMAN_EMIT_SYMBOL, 173), - (23, HUFFMAN_EMIT_SYMBOL, 173), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 131 - (3, HUFFMAN_EMIT_SYMBOL, 164), - (6, HUFFMAN_EMIT_SYMBOL, 164), - (10, HUFFMAN_EMIT_SYMBOL, 164), - (15, HUFFMAN_EMIT_SYMBOL, 164), - (24, HUFFMAN_EMIT_SYMBOL, 164), - (31, HUFFMAN_EMIT_SYMBOL, 164), - (41, HUFFMAN_EMIT_SYMBOL, 164), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (3, HUFFMAN_EMIT_SYMBOL, 169), - (6, HUFFMAN_EMIT_SYMBOL, 169), - (10, HUFFMAN_EMIT_SYMBOL, 169), - (15, HUFFMAN_EMIT_SYMBOL, 169), - (24, HUFFMAN_EMIT_SYMBOL, 169), - (31, HUFFMAN_EMIT_SYMBOL, 169), - (41, HUFFMAN_EMIT_SYMBOL, 169), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - - # Node 132 - (3, HUFFMAN_EMIT_SYMBOL, 170), - (6, HUFFMAN_EMIT_SYMBOL, 170), - (10, HUFFMAN_EMIT_SYMBOL, 170), - (15, HUFFMAN_EMIT_SYMBOL, 170), - (24, HUFFMAN_EMIT_SYMBOL, 170), - (31, HUFFMAN_EMIT_SYMBOL, 170), - (41, HUFFMAN_EMIT_SYMBOL, 170), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (3, HUFFMAN_EMIT_SYMBOL, 173), - (6, HUFFMAN_EMIT_SYMBOL, 173), - (10, HUFFMAN_EMIT_SYMBOL, 173), - (15, HUFFMAN_EMIT_SYMBOL, 173), - (24, HUFFMAN_EMIT_SYMBOL, 173), - (31, HUFFMAN_EMIT_SYMBOL, 173), - (41, HUFFMAN_EMIT_SYMBOL, 173), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 133 - (137, 0, 0), - (138, 0, 0), - (140, 0, 0), - (141, 0, 0), - (144, 0, 0), - (145, 0, 0), - (147, 0, 0), - (150, 0, 0), - (156, 0, 0), - (159, 0, 0), - (163, 0, 0), - (166, 0, 0), - (171, 0, 0), - (174, 0, 0), - (181, 0, 0), - (190, 0, 0), - - # Node 134 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - (148, 0, 0), - (149, 0, 0), - (151, 0, 0), - (152, 0, 0), - - # Node 135 - (1, HUFFMAN_EMIT_SYMBOL, 178), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (1, HUFFMAN_EMIT_SYMBOL, 181), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - (1, HUFFMAN_EMIT_SYMBOL, 185), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (1, HUFFMAN_EMIT_SYMBOL, 186), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - (1, HUFFMAN_EMIT_SYMBOL, 187), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (1, HUFFMAN_EMIT_SYMBOL, 189), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - (1, HUFFMAN_EMIT_SYMBOL, 190), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (1, HUFFMAN_EMIT_SYMBOL, 196), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - - # Node 136 - (2, HUFFMAN_EMIT_SYMBOL, 178), - (9, HUFFMAN_EMIT_SYMBOL, 178), - (23, HUFFMAN_EMIT_SYMBOL, 178), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (2, HUFFMAN_EMIT_SYMBOL, 181), - (9, HUFFMAN_EMIT_SYMBOL, 181), - (23, HUFFMAN_EMIT_SYMBOL, 181), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - (2, HUFFMAN_EMIT_SYMBOL, 185), - (9, HUFFMAN_EMIT_SYMBOL, 185), - (23, HUFFMAN_EMIT_SYMBOL, 185), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (2, HUFFMAN_EMIT_SYMBOL, 186), - (9, HUFFMAN_EMIT_SYMBOL, 186), - (23, HUFFMAN_EMIT_SYMBOL, 186), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - - # Node 137 - (3, HUFFMAN_EMIT_SYMBOL, 178), - (6, HUFFMAN_EMIT_SYMBOL, 178), - (10, HUFFMAN_EMIT_SYMBOL, 178), - (15, HUFFMAN_EMIT_SYMBOL, 178), - (24, HUFFMAN_EMIT_SYMBOL, 178), - (31, HUFFMAN_EMIT_SYMBOL, 178), - (41, HUFFMAN_EMIT_SYMBOL, 178), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (3, HUFFMAN_EMIT_SYMBOL, 181), - (6, HUFFMAN_EMIT_SYMBOL, 181), - (10, HUFFMAN_EMIT_SYMBOL, 181), - (15, HUFFMAN_EMIT_SYMBOL, 181), - (24, HUFFMAN_EMIT_SYMBOL, 181), - (31, HUFFMAN_EMIT_SYMBOL, 181), - (41, HUFFMAN_EMIT_SYMBOL, 181), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - - # Node 138 - (3, HUFFMAN_EMIT_SYMBOL, 185), - (6, HUFFMAN_EMIT_SYMBOL, 185), - (10, HUFFMAN_EMIT_SYMBOL, 185), - (15, HUFFMAN_EMIT_SYMBOL, 185), - (24, HUFFMAN_EMIT_SYMBOL, 185), - (31, HUFFMAN_EMIT_SYMBOL, 185), - (41, HUFFMAN_EMIT_SYMBOL, 185), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (3, HUFFMAN_EMIT_SYMBOL, 186), - (6, HUFFMAN_EMIT_SYMBOL, 186), - (10, HUFFMAN_EMIT_SYMBOL, 186), - (15, HUFFMAN_EMIT_SYMBOL, 186), - (24, HUFFMAN_EMIT_SYMBOL, 186), - (31, HUFFMAN_EMIT_SYMBOL, 186), - (41, HUFFMAN_EMIT_SYMBOL, 186), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - - # Node 139 - (2, HUFFMAN_EMIT_SYMBOL, 187), - (9, HUFFMAN_EMIT_SYMBOL, 187), - (23, HUFFMAN_EMIT_SYMBOL, 187), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (2, HUFFMAN_EMIT_SYMBOL, 189), - (9, HUFFMAN_EMIT_SYMBOL, 189), - (23, HUFFMAN_EMIT_SYMBOL, 189), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - (2, HUFFMAN_EMIT_SYMBOL, 190), - (9, HUFFMAN_EMIT_SYMBOL, 190), - (23, HUFFMAN_EMIT_SYMBOL, 190), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (2, HUFFMAN_EMIT_SYMBOL, 196), - (9, HUFFMAN_EMIT_SYMBOL, 196), - (23, HUFFMAN_EMIT_SYMBOL, 196), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - - # Node 140 - (3, HUFFMAN_EMIT_SYMBOL, 187), - (6, HUFFMAN_EMIT_SYMBOL, 187), - (10, HUFFMAN_EMIT_SYMBOL, 187), - (15, HUFFMAN_EMIT_SYMBOL, 187), - (24, HUFFMAN_EMIT_SYMBOL, 187), - (31, HUFFMAN_EMIT_SYMBOL, 187), - (41, HUFFMAN_EMIT_SYMBOL, 187), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (3, HUFFMAN_EMIT_SYMBOL, 189), - (6, HUFFMAN_EMIT_SYMBOL, 189), - (10, HUFFMAN_EMIT_SYMBOL, 189), - (15, HUFFMAN_EMIT_SYMBOL, 189), - (24, HUFFMAN_EMIT_SYMBOL, 189), - (31, HUFFMAN_EMIT_SYMBOL, 189), - (41, HUFFMAN_EMIT_SYMBOL, 189), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - - # Node 141 - (3, HUFFMAN_EMIT_SYMBOL, 190), - (6, HUFFMAN_EMIT_SYMBOL, 190), - (10, HUFFMAN_EMIT_SYMBOL, 190), - (15, HUFFMAN_EMIT_SYMBOL, 190), - (24, HUFFMAN_EMIT_SYMBOL, 190), - (31, HUFFMAN_EMIT_SYMBOL, 190), - (41, HUFFMAN_EMIT_SYMBOL, 190), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (3, HUFFMAN_EMIT_SYMBOL, 196), - (6, HUFFMAN_EMIT_SYMBOL, 196), - (10, HUFFMAN_EMIT_SYMBOL, 196), - (15, HUFFMAN_EMIT_SYMBOL, 196), - (24, HUFFMAN_EMIT_SYMBOL, 196), - (31, HUFFMAN_EMIT_SYMBOL, 196), - (41, HUFFMAN_EMIT_SYMBOL, 196), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - - # Node 142 - (1, HUFFMAN_EMIT_SYMBOL, 198), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (1, HUFFMAN_EMIT_SYMBOL, 228), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - (1, HUFFMAN_EMIT_SYMBOL, 232), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (1, HUFFMAN_EMIT_SYMBOL, 233), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 143 - (2, HUFFMAN_EMIT_SYMBOL, 198), - (9, HUFFMAN_EMIT_SYMBOL, 198), - (23, HUFFMAN_EMIT_SYMBOL, 198), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (2, HUFFMAN_EMIT_SYMBOL, 228), - (9, HUFFMAN_EMIT_SYMBOL, 228), - (23, HUFFMAN_EMIT_SYMBOL, 228), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - (2, HUFFMAN_EMIT_SYMBOL, 232), - (9, HUFFMAN_EMIT_SYMBOL, 232), - (23, HUFFMAN_EMIT_SYMBOL, 232), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (2, HUFFMAN_EMIT_SYMBOL, 233), - (9, HUFFMAN_EMIT_SYMBOL, 233), - (23, HUFFMAN_EMIT_SYMBOL, 233), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - - # Node 144 - (3, HUFFMAN_EMIT_SYMBOL, 198), - (6, HUFFMAN_EMIT_SYMBOL, 198), - (10, HUFFMAN_EMIT_SYMBOL, 198), - (15, HUFFMAN_EMIT_SYMBOL, 198), - (24, HUFFMAN_EMIT_SYMBOL, 198), - (31, HUFFMAN_EMIT_SYMBOL, 198), - (41, HUFFMAN_EMIT_SYMBOL, 198), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (3, HUFFMAN_EMIT_SYMBOL, 228), - (6, HUFFMAN_EMIT_SYMBOL, 228), - (10, HUFFMAN_EMIT_SYMBOL, 228), - (15, HUFFMAN_EMIT_SYMBOL, 228), - (24, HUFFMAN_EMIT_SYMBOL, 228), - (31, HUFFMAN_EMIT_SYMBOL, 228), - (41, HUFFMAN_EMIT_SYMBOL, 228), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - - # Node 145 - (3, HUFFMAN_EMIT_SYMBOL, 232), - (6, HUFFMAN_EMIT_SYMBOL, 232), - (10, HUFFMAN_EMIT_SYMBOL, 232), - (15, HUFFMAN_EMIT_SYMBOL, 232), - (24, HUFFMAN_EMIT_SYMBOL, 232), - (31, HUFFMAN_EMIT_SYMBOL, 232), - (41, HUFFMAN_EMIT_SYMBOL, 232), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (3, HUFFMAN_EMIT_SYMBOL, 233), - (6, HUFFMAN_EMIT_SYMBOL, 233), - (10, HUFFMAN_EMIT_SYMBOL, 233), - (15, HUFFMAN_EMIT_SYMBOL, 233), - (24, HUFFMAN_EMIT_SYMBOL, 233), - (31, HUFFMAN_EMIT_SYMBOL, 233), - (41, HUFFMAN_EMIT_SYMBOL, 233), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - - # Node 146 - (1, HUFFMAN_EMIT_SYMBOL, 1), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (1, HUFFMAN_EMIT_SYMBOL, 135), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - (1, HUFFMAN_EMIT_SYMBOL, 137), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (1, HUFFMAN_EMIT_SYMBOL, 138), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - (1, HUFFMAN_EMIT_SYMBOL, 139), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (1, HUFFMAN_EMIT_SYMBOL, 140), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - (1, HUFFMAN_EMIT_SYMBOL, 141), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (1, HUFFMAN_EMIT_SYMBOL, 143), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 147 - (2, HUFFMAN_EMIT_SYMBOL, 1), - (9, HUFFMAN_EMIT_SYMBOL, 1), - (23, HUFFMAN_EMIT_SYMBOL, 1), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (2, HUFFMAN_EMIT_SYMBOL, 135), - (9, HUFFMAN_EMIT_SYMBOL, 135), - (23, HUFFMAN_EMIT_SYMBOL, 135), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - (2, HUFFMAN_EMIT_SYMBOL, 137), - (9, HUFFMAN_EMIT_SYMBOL, 137), - (23, HUFFMAN_EMIT_SYMBOL, 137), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (2, HUFFMAN_EMIT_SYMBOL, 138), - (9, HUFFMAN_EMIT_SYMBOL, 138), - (23, HUFFMAN_EMIT_SYMBOL, 138), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - - # Node 148 - (3, HUFFMAN_EMIT_SYMBOL, 1), - (6, HUFFMAN_EMIT_SYMBOL, 1), - (10, HUFFMAN_EMIT_SYMBOL, 1), - (15, HUFFMAN_EMIT_SYMBOL, 1), - (24, HUFFMAN_EMIT_SYMBOL, 1), - (31, HUFFMAN_EMIT_SYMBOL, 1), - (41, HUFFMAN_EMIT_SYMBOL, 1), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (3, HUFFMAN_EMIT_SYMBOL, 135), - (6, HUFFMAN_EMIT_SYMBOL, 135), - (10, HUFFMAN_EMIT_SYMBOL, 135), - (15, HUFFMAN_EMIT_SYMBOL, 135), - (24, HUFFMAN_EMIT_SYMBOL, 135), - (31, HUFFMAN_EMIT_SYMBOL, 135), - (41, HUFFMAN_EMIT_SYMBOL, 135), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - - # Node 149 - (3, HUFFMAN_EMIT_SYMBOL, 137), - (6, HUFFMAN_EMIT_SYMBOL, 137), - (10, HUFFMAN_EMIT_SYMBOL, 137), - (15, HUFFMAN_EMIT_SYMBOL, 137), - (24, HUFFMAN_EMIT_SYMBOL, 137), - (31, HUFFMAN_EMIT_SYMBOL, 137), - (41, HUFFMAN_EMIT_SYMBOL, 137), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (3, HUFFMAN_EMIT_SYMBOL, 138), - (6, HUFFMAN_EMIT_SYMBOL, 138), - (10, HUFFMAN_EMIT_SYMBOL, 138), - (15, HUFFMAN_EMIT_SYMBOL, 138), - (24, HUFFMAN_EMIT_SYMBOL, 138), - (31, HUFFMAN_EMIT_SYMBOL, 138), - (41, HUFFMAN_EMIT_SYMBOL, 138), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - - # Node 150 - (2, HUFFMAN_EMIT_SYMBOL, 139), - (9, HUFFMAN_EMIT_SYMBOL, 139), - (23, HUFFMAN_EMIT_SYMBOL, 139), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (2, HUFFMAN_EMIT_SYMBOL, 140), - (9, HUFFMAN_EMIT_SYMBOL, 140), - (23, HUFFMAN_EMIT_SYMBOL, 140), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - (2, HUFFMAN_EMIT_SYMBOL, 141), - (9, HUFFMAN_EMIT_SYMBOL, 141), - (23, HUFFMAN_EMIT_SYMBOL, 141), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (2, HUFFMAN_EMIT_SYMBOL, 143), - (9, HUFFMAN_EMIT_SYMBOL, 143), - (23, HUFFMAN_EMIT_SYMBOL, 143), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 151 - (3, HUFFMAN_EMIT_SYMBOL, 139), - (6, HUFFMAN_EMIT_SYMBOL, 139), - (10, HUFFMAN_EMIT_SYMBOL, 139), - (15, HUFFMAN_EMIT_SYMBOL, 139), - (24, HUFFMAN_EMIT_SYMBOL, 139), - (31, HUFFMAN_EMIT_SYMBOL, 139), - (41, HUFFMAN_EMIT_SYMBOL, 139), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (3, HUFFMAN_EMIT_SYMBOL, 140), - (6, HUFFMAN_EMIT_SYMBOL, 140), - (10, HUFFMAN_EMIT_SYMBOL, 140), - (15, HUFFMAN_EMIT_SYMBOL, 140), - (24, HUFFMAN_EMIT_SYMBOL, 140), - (31, HUFFMAN_EMIT_SYMBOL, 140), - (41, HUFFMAN_EMIT_SYMBOL, 140), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - - # Node 152 - (3, HUFFMAN_EMIT_SYMBOL, 141), - (6, HUFFMAN_EMIT_SYMBOL, 141), - (10, HUFFMAN_EMIT_SYMBOL, 141), - (15, HUFFMAN_EMIT_SYMBOL, 141), - (24, HUFFMAN_EMIT_SYMBOL, 141), - (31, HUFFMAN_EMIT_SYMBOL, 141), - (41, HUFFMAN_EMIT_SYMBOL, 141), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (3, HUFFMAN_EMIT_SYMBOL, 143), - (6, HUFFMAN_EMIT_SYMBOL, 143), - (10, HUFFMAN_EMIT_SYMBOL, 143), - (15, HUFFMAN_EMIT_SYMBOL, 143), - (24, HUFFMAN_EMIT_SYMBOL, 143), - (31, HUFFMAN_EMIT_SYMBOL, 143), - (41, HUFFMAN_EMIT_SYMBOL, 143), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 153 - (157, 0, 0), - (158, 0, 0), - (160, 0, 0), - (161, 0, 0), - (164, 0, 0), - (165, 0, 0), - (167, 0, 0), - (168, 0, 0), - (172, 0, 0), - (173, 0, 0), - (175, 0, 0), - (177, 0, 0), - (182, 0, 0), - (185, 0, 0), - (191, 0, 0), - (207, 0, 0), - - # Node 154 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 155 - (1, HUFFMAN_EMIT_SYMBOL, 147), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (1, HUFFMAN_EMIT_SYMBOL, 149), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - (1, HUFFMAN_EMIT_SYMBOL, 150), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (1, HUFFMAN_EMIT_SYMBOL, 151), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - (1, HUFFMAN_EMIT_SYMBOL, 152), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (1, HUFFMAN_EMIT_SYMBOL, 155), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - (1, HUFFMAN_EMIT_SYMBOL, 157), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (1, HUFFMAN_EMIT_SYMBOL, 158), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - - # Node 156 - (2, HUFFMAN_EMIT_SYMBOL, 147), - (9, HUFFMAN_EMIT_SYMBOL, 147), - (23, HUFFMAN_EMIT_SYMBOL, 147), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (2, HUFFMAN_EMIT_SYMBOL, 149), - (9, HUFFMAN_EMIT_SYMBOL, 149), - (23, HUFFMAN_EMIT_SYMBOL, 149), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - (2, HUFFMAN_EMIT_SYMBOL, 150), - (9, HUFFMAN_EMIT_SYMBOL, 150), - (23, HUFFMAN_EMIT_SYMBOL, 150), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (2, HUFFMAN_EMIT_SYMBOL, 151), - (9, HUFFMAN_EMIT_SYMBOL, 151), - (23, HUFFMAN_EMIT_SYMBOL, 151), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - - # Node 157 - (3, HUFFMAN_EMIT_SYMBOL, 147), - (6, HUFFMAN_EMIT_SYMBOL, 147), - (10, HUFFMAN_EMIT_SYMBOL, 147), - (15, HUFFMAN_EMIT_SYMBOL, 147), - (24, HUFFMAN_EMIT_SYMBOL, 147), - (31, HUFFMAN_EMIT_SYMBOL, 147), - (41, HUFFMAN_EMIT_SYMBOL, 147), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (3, HUFFMAN_EMIT_SYMBOL, 149), - (6, HUFFMAN_EMIT_SYMBOL, 149), - (10, HUFFMAN_EMIT_SYMBOL, 149), - (15, HUFFMAN_EMIT_SYMBOL, 149), - (24, HUFFMAN_EMIT_SYMBOL, 149), - (31, HUFFMAN_EMIT_SYMBOL, 149), - (41, HUFFMAN_EMIT_SYMBOL, 149), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - - # Node 158 - (3, HUFFMAN_EMIT_SYMBOL, 150), - (6, HUFFMAN_EMIT_SYMBOL, 150), - (10, HUFFMAN_EMIT_SYMBOL, 150), - (15, HUFFMAN_EMIT_SYMBOL, 150), - (24, HUFFMAN_EMIT_SYMBOL, 150), - (31, HUFFMAN_EMIT_SYMBOL, 150), - (41, HUFFMAN_EMIT_SYMBOL, 150), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (3, HUFFMAN_EMIT_SYMBOL, 151), - (6, HUFFMAN_EMIT_SYMBOL, 151), - (10, HUFFMAN_EMIT_SYMBOL, 151), - (15, HUFFMAN_EMIT_SYMBOL, 151), - (24, HUFFMAN_EMIT_SYMBOL, 151), - (31, HUFFMAN_EMIT_SYMBOL, 151), - (41, HUFFMAN_EMIT_SYMBOL, 151), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - - # Node 159 - (2, HUFFMAN_EMIT_SYMBOL, 152), - (9, HUFFMAN_EMIT_SYMBOL, 152), - (23, HUFFMAN_EMIT_SYMBOL, 152), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (2, HUFFMAN_EMIT_SYMBOL, 155), - (9, HUFFMAN_EMIT_SYMBOL, 155), - (23, HUFFMAN_EMIT_SYMBOL, 155), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - (2, HUFFMAN_EMIT_SYMBOL, 157), - (9, HUFFMAN_EMIT_SYMBOL, 157), - (23, HUFFMAN_EMIT_SYMBOL, 157), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (2, HUFFMAN_EMIT_SYMBOL, 158), - (9, HUFFMAN_EMIT_SYMBOL, 158), - (23, HUFFMAN_EMIT_SYMBOL, 158), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - - # Node 160 - (3, HUFFMAN_EMIT_SYMBOL, 152), - (6, HUFFMAN_EMIT_SYMBOL, 152), - (10, HUFFMAN_EMIT_SYMBOL, 152), - (15, HUFFMAN_EMIT_SYMBOL, 152), - (24, HUFFMAN_EMIT_SYMBOL, 152), - (31, HUFFMAN_EMIT_SYMBOL, 152), - (41, HUFFMAN_EMIT_SYMBOL, 152), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (3, HUFFMAN_EMIT_SYMBOL, 155), - (6, HUFFMAN_EMIT_SYMBOL, 155), - (10, HUFFMAN_EMIT_SYMBOL, 155), - (15, HUFFMAN_EMIT_SYMBOL, 155), - (24, HUFFMAN_EMIT_SYMBOL, 155), - (31, HUFFMAN_EMIT_SYMBOL, 155), - (41, HUFFMAN_EMIT_SYMBOL, 155), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - - # Node 161 - (3, HUFFMAN_EMIT_SYMBOL, 157), - (6, HUFFMAN_EMIT_SYMBOL, 157), - (10, HUFFMAN_EMIT_SYMBOL, 157), - (15, HUFFMAN_EMIT_SYMBOL, 157), - (24, HUFFMAN_EMIT_SYMBOL, 157), - (31, HUFFMAN_EMIT_SYMBOL, 157), - (41, HUFFMAN_EMIT_SYMBOL, 157), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (3, HUFFMAN_EMIT_SYMBOL, 158), - (6, HUFFMAN_EMIT_SYMBOL, 158), - (10, HUFFMAN_EMIT_SYMBOL, 158), - (15, HUFFMAN_EMIT_SYMBOL, 158), - (24, HUFFMAN_EMIT_SYMBOL, 158), - (31, HUFFMAN_EMIT_SYMBOL, 158), - (41, HUFFMAN_EMIT_SYMBOL, 158), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - - # Node 162 - (1, HUFFMAN_EMIT_SYMBOL, 165), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (1, HUFFMAN_EMIT_SYMBOL, 166), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - (1, HUFFMAN_EMIT_SYMBOL, 168), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (1, HUFFMAN_EMIT_SYMBOL, 174), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - (1, HUFFMAN_EMIT_SYMBOL, 175), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (1, HUFFMAN_EMIT_SYMBOL, 180), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - (1, HUFFMAN_EMIT_SYMBOL, 182), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (1, HUFFMAN_EMIT_SYMBOL, 183), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 163 - (2, HUFFMAN_EMIT_SYMBOL, 165), - (9, HUFFMAN_EMIT_SYMBOL, 165), - (23, HUFFMAN_EMIT_SYMBOL, 165), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (2, HUFFMAN_EMIT_SYMBOL, 166), - (9, HUFFMAN_EMIT_SYMBOL, 166), - (23, HUFFMAN_EMIT_SYMBOL, 166), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - (2, HUFFMAN_EMIT_SYMBOL, 168), - (9, HUFFMAN_EMIT_SYMBOL, 168), - (23, HUFFMAN_EMIT_SYMBOL, 168), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (2, HUFFMAN_EMIT_SYMBOL, 174), - (9, HUFFMAN_EMIT_SYMBOL, 174), - (23, HUFFMAN_EMIT_SYMBOL, 174), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - - # Node 164 - (3, HUFFMAN_EMIT_SYMBOL, 165), - (6, HUFFMAN_EMIT_SYMBOL, 165), - (10, HUFFMAN_EMIT_SYMBOL, 165), - (15, HUFFMAN_EMIT_SYMBOL, 165), - (24, HUFFMAN_EMIT_SYMBOL, 165), - (31, HUFFMAN_EMIT_SYMBOL, 165), - (41, HUFFMAN_EMIT_SYMBOL, 165), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (3, HUFFMAN_EMIT_SYMBOL, 166), - (6, HUFFMAN_EMIT_SYMBOL, 166), - (10, HUFFMAN_EMIT_SYMBOL, 166), - (15, HUFFMAN_EMIT_SYMBOL, 166), - (24, HUFFMAN_EMIT_SYMBOL, 166), - (31, HUFFMAN_EMIT_SYMBOL, 166), - (41, HUFFMAN_EMIT_SYMBOL, 166), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - - # Node 165 - (3, HUFFMAN_EMIT_SYMBOL, 168), - (6, HUFFMAN_EMIT_SYMBOL, 168), - (10, HUFFMAN_EMIT_SYMBOL, 168), - (15, HUFFMAN_EMIT_SYMBOL, 168), - (24, HUFFMAN_EMIT_SYMBOL, 168), - (31, HUFFMAN_EMIT_SYMBOL, 168), - (41, HUFFMAN_EMIT_SYMBOL, 168), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (3, HUFFMAN_EMIT_SYMBOL, 174), - (6, HUFFMAN_EMIT_SYMBOL, 174), - (10, HUFFMAN_EMIT_SYMBOL, 174), - (15, HUFFMAN_EMIT_SYMBOL, 174), - (24, HUFFMAN_EMIT_SYMBOL, 174), - (31, HUFFMAN_EMIT_SYMBOL, 174), - (41, HUFFMAN_EMIT_SYMBOL, 174), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - - # Node 166 - (2, HUFFMAN_EMIT_SYMBOL, 175), - (9, HUFFMAN_EMIT_SYMBOL, 175), - (23, HUFFMAN_EMIT_SYMBOL, 175), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (2, HUFFMAN_EMIT_SYMBOL, 180), - (9, HUFFMAN_EMIT_SYMBOL, 180), - (23, HUFFMAN_EMIT_SYMBOL, 180), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - (2, HUFFMAN_EMIT_SYMBOL, 182), - (9, HUFFMAN_EMIT_SYMBOL, 182), - (23, HUFFMAN_EMIT_SYMBOL, 182), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (2, HUFFMAN_EMIT_SYMBOL, 183), - (9, HUFFMAN_EMIT_SYMBOL, 183), - (23, HUFFMAN_EMIT_SYMBOL, 183), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 167 - (3, HUFFMAN_EMIT_SYMBOL, 175), - (6, HUFFMAN_EMIT_SYMBOL, 175), - (10, HUFFMAN_EMIT_SYMBOL, 175), - (15, HUFFMAN_EMIT_SYMBOL, 175), - (24, HUFFMAN_EMIT_SYMBOL, 175), - (31, HUFFMAN_EMIT_SYMBOL, 175), - (41, HUFFMAN_EMIT_SYMBOL, 175), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (3, HUFFMAN_EMIT_SYMBOL, 180), - (6, HUFFMAN_EMIT_SYMBOL, 180), - (10, HUFFMAN_EMIT_SYMBOL, 180), - (15, HUFFMAN_EMIT_SYMBOL, 180), - (24, HUFFMAN_EMIT_SYMBOL, 180), - (31, HUFFMAN_EMIT_SYMBOL, 180), - (41, HUFFMAN_EMIT_SYMBOL, 180), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - - # Node 168 - (3, HUFFMAN_EMIT_SYMBOL, 182), - (6, HUFFMAN_EMIT_SYMBOL, 182), - (10, HUFFMAN_EMIT_SYMBOL, 182), - (15, HUFFMAN_EMIT_SYMBOL, 182), - (24, HUFFMAN_EMIT_SYMBOL, 182), - (31, HUFFMAN_EMIT_SYMBOL, 182), - (41, HUFFMAN_EMIT_SYMBOL, 182), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (3, HUFFMAN_EMIT_SYMBOL, 183), - (6, HUFFMAN_EMIT_SYMBOL, 183), - (10, HUFFMAN_EMIT_SYMBOL, 183), - (15, HUFFMAN_EMIT_SYMBOL, 183), - (24, HUFFMAN_EMIT_SYMBOL, 183), - (31, HUFFMAN_EMIT_SYMBOL, 183), - (41, HUFFMAN_EMIT_SYMBOL, 183), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 169 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (176, 0, 0), - (178, 0, 0), - (179, 0, 0), - (183, 0, 0), - (184, 0, 0), - (186, 0, 0), - (187, 0, 0), - (192, 0, 0), - (199, 0, 0), - (208, 0, 0), - (223, 0, 0), - - # Node 170 - (1, HUFFMAN_EMIT_SYMBOL, 188), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (1, HUFFMAN_EMIT_SYMBOL, 191), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - (1, HUFFMAN_EMIT_SYMBOL, 197), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (1, HUFFMAN_EMIT_SYMBOL, 231), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - (1, HUFFMAN_EMIT_SYMBOL, 239), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 171 - (2, HUFFMAN_EMIT_SYMBOL, 188), - (9, HUFFMAN_EMIT_SYMBOL, 188), - (23, HUFFMAN_EMIT_SYMBOL, 188), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (2, HUFFMAN_EMIT_SYMBOL, 191), - (9, HUFFMAN_EMIT_SYMBOL, 191), - (23, HUFFMAN_EMIT_SYMBOL, 191), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - (2, HUFFMAN_EMIT_SYMBOL, 197), - (9, HUFFMAN_EMIT_SYMBOL, 197), - (23, HUFFMAN_EMIT_SYMBOL, 197), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (2, HUFFMAN_EMIT_SYMBOL, 231), - (9, HUFFMAN_EMIT_SYMBOL, 231), - (23, HUFFMAN_EMIT_SYMBOL, 231), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - - # Node 172 - (3, HUFFMAN_EMIT_SYMBOL, 188), - (6, HUFFMAN_EMIT_SYMBOL, 188), - (10, HUFFMAN_EMIT_SYMBOL, 188), - (15, HUFFMAN_EMIT_SYMBOL, 188), - (24, HUFFMAN_EMIT_SYMBOL, 188), - (31, HUFFMAN_EMIT_SYMBOL, 188), - (41, HUFFMAN_EMIT_SYMBOL, 188), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (3, HUFFMAN_EMIT_SYMBOL, 191), - (6, HUFFMAN_EMIT_SYMBOL, 191), - (10, HUFFMAN_EMIT_SYMBOL, 191), - (15, HUFFMAN_EMIT_SYMBOL, 191), - (24, HUFFMAN_EMIT_SYMBOL, 191), - (31, HUFFMAN_EMIT_SYMBOL, 191), - (41, HUFFMAN_EMIT_SYMBOL, 191), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - - # Node 173 - (3, HUFFMAN_EMIT_SYMBOL, 197), - (6, HUFFMAN_EMIT_SYMBOL, 197), - (10, HUFFMAN_EMIT_SYMBOL, 197), - (15, HUFFMAN_EMIT_SYMBOL, 197), - (24, HUFFMAN_EMIT_SYMBOL, 197), - (31, HUFFMAN_EMIT_SYMBOL, 197), - (41, HUFFMAN_EMIT_SYMBOL, 197), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (3, HUFFMAN_EMIT_SYMBOL, 231), - (6, HUFFMAN_EMIT_SYMBOL, 231), - (10, HUFFMAN_EMIT_SYMBOL, 231), - (15, HUFFMAN_EMIT_SYMBOL, 231), - (24, HUFFMAN_EMIT_SYMBOL, 231), - (31, HUFFMAN_EMIT_SYMBOL, 231), - (41, HUFFMAN_EMIT_SYMBOL, 231), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - - # Node 174 - (2, HUFFMAN_EMIT_SYMBOL, 239), - (9, HUFFMAN_EMIT_SYMBOL, 239), - (23, HUFFMAN_EMIT_SYMBOL, 239), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (1, HUFFMAN_EMIT_SYMBOL, 9), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (1, HUFFMAN_EMIT_SYMBOL, 142), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - (1, HUFFMAN_EMIT_SYMBOL, 144), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (1, HUFFMAN_EMIT_SYMBOL, 145), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - (1, HUFFMAN_EMIT_SYMBOL, 148), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (1, HUFFMAN_EMIT_SYMBOL, 159), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 175 - (3, HUFFMAN_EMIT_SYMBOL, 239), - (6, HUFFMAN_EMIT_SYMBOL, 239), - (10, HUFFMAN_EMIT_SYMBOL, 239), - (15, HUFFMAN_EMIT_SYMBOL, 239), - (24, HUFFMAN_EMIT_SYMBOL, 239), - (31, HUFFMAN_EMIT_SYMBOL, 239), - (41, HUFFMAN_EMIT_SYMBOL, 239), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (2, HUFFMAN_EMIT_SYMBOL, 9), - (9, HUFFMAN_EMIT_SYMBOL, 9), - (23, HUFFMAN_EMIT_SYMBOL, 9), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (2, HUFFMAN_EMIT_SYMBOL, 142), - (9, HUFFMAN_EMIT_SYMBOL, 142), - (23, HUFFMAN_EMIT_SYMBOL, 142), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - - # Node 176 - (3, HUFFMAN_EMIT_SYMBOL, 9), - (6, HUFFMAN_EMIT_SYMBOL, 9), - (10, HUFFMAN_EMIT_SYMBOL, 9), - (15, HUFFMAN_EMIT_SYMBOL, 9), - (24, HUFFMAN_EMIT_SYMBOL, 9), - (31, HUFFMAN_EMIT_SYMBOL, 9), - (41, HUFFMAN_EMIT_SYMBOL, 9), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (3, HUFFMAN_EMIT_SYMBOL, 142), - (6, HUFFMAN_EMIT_SYMBOL, 142), - (10, HUFFMAN_EMIT_SYMBOL, 142), - (15, HUFFMAN_EMIT_SYMBOL, 142), - (24, HUFFMAN_EMIT_SYMBOL, 142), - (31, HUFFMAN_EMIT_SYMBOL, 142), - (41, HUFFMAN_EMIT_SYMBOL, 142), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - - # Node 177 - (2, HUFFMAN_EMIT_SYMBOL, 144), - (9, HUFFMAN_EMIT_SYMBOL, 144), - (23, HUFFMAN_EMIT_SYMBOL, 144), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (2, HUFFMAN_EMIT_SYMBOL, 145), - (9, HUFFMAN_EMIT_SYMBOL, 145), - (23, HUFFMAN_EMIT_SYMBOL, 145), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - (2, HUFFMAN_EMIT_SYMBOL, 148), - (9, HUFFMAN_EMIT_SYMBOL, 148), - (23, HUFFMAN_EMIT_SYMBOL, 148), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (2, HUFFMAN_EMIT_SYMBOL, 159), - (9, HUFFMAN_EMIT_SYMBOL, 159), - (23, HUFFMAN_EMIT_SYMBOL, 159), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 178 - (3, HUFFMAN_EMIT_SYMBOL, 144), - (6, HUFFMAN_EMIT_SYMBOL, 144), - (10, HUFFMAN_EMIT_SYMBOL, 144), - (15, HUFFMAN_EMIT_SYMBOL, 144), - (24, HUFFMAN_EMIT_SYMBOL, 144), - (31, HUFFMAN_EMIT_SYMBOL, 144), - (41, HUFFMAN_EMIT_SYMBOL, 144), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (3, HUFFMAN_EMIT_SYMBOL, 145), - (6, HUFFMAN_EMIT_SYMBOL, 145), - (10, HUFFMAN_EMIT_SYMBOL, 145), - (15, HUFFMAN_EMIT_SYMBOL, 145), - (24, HUFFMAN_EMIT_SYMBOL, 145), - (31, HUFFMAN_EMIT_SYMBOL, 145), - (41, HUFFMAN_EMIT_SYMBOL, 145), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - - # Node 179 - (3, HUFFMAN_EMIT_SYMBOL, 148), - (6, HUFFMAN_EMIT_SYMBOL, 148), - (10, HUFFMAN_EMIT_SYMBOL, 148), - (15, HUFFMAN_EMIT_SYMBOL, 148), - (24, HUFFMAN_EMIT_SYMBOL, 148), - (31, HUFFMAN_EMIT_SYMBOL, 148), - (41, HUFFMAN_EMIT_SYMBOL, 148), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (3, HUFFMAN_EMIT_SYMBOL, 159), - (6, HUFFMAN_EMIT_SYMBOL, 159), - (10, HUFFMAN_EMIT_SYMBOL, 159), - (15, HUFFMAN_EMIT_SYMBOL, 159), - (24, HUFFMAN_EMIT_SYMBOL, 159), - (31, HUFFMAN_EMIT_SYMBOL, 159), - (41, HUFFMAN_EMIT_SYMBOL, 159), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 180 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - (188, 0, 0), - (189, 0, 0), - (193, 0, 0), - (196, 0, 0), - (200, 0, 0), - (203, 0, 0), - (209, 0, 0), - (216, 0, 0), - (224, 0, 0), - (238, 0, 0), - - # Node 181 - (1, HUFFMAN_EMIT_SYMBOL, 171), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (1, HUFFMAN_EMIT_SYMBOL, 206), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - (1, HUFFMAN_EMIT_SYMBOL, 215), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (1, HUFFMAN_EMIT_SYMBOL, 225), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - (1, HUFFMAN_EMIT_SYMBOL, 236), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (1, HUFFMAN_EMIT_SYMBOL, 237), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 182 - (2, HUFFMAN_EMIT_SYMBOL, 171), - (9, HUFFMAN_EMIT_SYMBOL, 171), - (23, HUFFMAN_EMIT_SYMBOL, 171), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (2, HUFFMAN_EMIT_SYMBOL, 206), - (9, HUFFMAN_EMIT_SYMBOL, 206), - (23, HUFFMAN_EMIT_SYMBOL, 206), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - (2, HUFFMAN_EMIT_SYMBOL, 215), - (9, HUFFMAN_EMIT_SYMBOL, 215), - (23, HUFFMAN_EMIT_SYMBOL, 215), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (2, HUFFMAN_EMIT_SYMBOL, 225), - (9, HUFFMAN_EMIT_SYMBOL, 225), - (23, HUFFMAN_EMIT_SYMBOL, 225), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - - # Node 183 - (3, HUFFMAN_EMIT_SYMBOL, 171), - (6, HUFFMAN_EMIT_SYMBOL, 171), - (10, HUFFMAN_EMIT_SYMBOL, 171), - (15, HUFFMAN_EMIT_SYMBOL, 171), - (24, HUFFMAN_EMIT_SYMBOL, 171), - (31, HUFFMAN_EMIT_SYMBOL, 171), - (41, HUFFMAN_EMIT_SYMBOL, 171), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (3, HUFFMAN_EMIT_SYMBOL, 206), - (6, HUFFMAN_EMIT_SYMBOL, 206), - (10, HUFFMAN_EMIT_SYMBOL, 206), - (15, HUFFMAN_EMIT_SYMBOL, 206), - (24, HUFFMAN_EMIT_SYMBOL, 206), - (31, HUFFMAN_EMIT_SYMBOL, 206), - (41, HUFFMAN_EMIT_SYMBOL, 206), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - - # Node 184 - (3, HUFFMAN_EMIT_SYMBOL, 215), - (6, HUFFMAN_EMIT_SYMBOL, 215), - (10, HUFFMAN_EMIT_SYMBOL, 215), - (15, HUFFMAN_EMIT_SYMBOL, 215), - (24, HUFFMAN_EMIT_SYMBOL, 215), - (31, HUFFMAN_EMIT_SYMBOL, 215), - (41, HUFFMAN_EMIT_SYMBOL, 215), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (3, HUFFMAN_EMIT_SYMBOL, 225), - (6, HUFFMAN_EMIT_SYMBOL, 225), - (10, HUFFMAN_EMIT_SYMBOL, 225), - (15, HUFFMAN_EMIT_SYMBOL, 225), - (24, HUFFMAN_EMIT_SYMBOL, 225), - (31, HUFFMAN_EMIT_SYMBOL, 225), - (41, HUFFMAN_EMIT_SYMBOL, 225), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - - # Node 185 - (2, HUFFMAN_EMIT_SYMBOL, 236), - (9, HUFFMAN_EMIT_SYMBOL, 236), - (23, HUFFMAN_EMIT_SYMBOL, 236), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (2, HUFFMAN_EMIT_SYMBOL, 237), - (9, HUFFMAN_EMIT_SYMBOL, 237), - (23, HUFFMAN_EMIT_SYMBOL, 237), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - (1, HUFFMAN_EMIT_SYMBOL, 199), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (1, HUFFMAN_EMIT_SYMBOL, 207), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - (1, HUFFMAN_EMIT_SYMBOL, 234), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (1, HUFFMAN_EMIT_SYMBOL, 235), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 186 - (3, HUFFMAN_EMIT_SYMBOL, 236), - (6, HUFFMAN_EMIT_SYMBOL, 236), - (10, HUFFMAN_EMIT_SYMBOL, 236), - (15, HUFFMAN_EMIT_SYMBOL, 236), - (24, HUFFMAN_EMIT_SYMBOL, 236), - (31, HUFFMAN_EMIT_SYMBOL, 236), - (41, HUFFMAN_EMIT_SYMBOL, 236), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (3, HUFFMAN_EMIT_SYMBOL, 237), - (6, HUFFMAN_EMIT_SYMBOL, 237), - (10, HUFFMAN_EMIT_SYMBOL, 237), - (15, HUFFMAN_EMIT_SYMBOL, 237), - (24, HUFFMAN_EMIT_SYMBOL, 237), - (31, HUFFMAN_EMIT_SYMBOL, 237), - (41, HUFFMAN_EMIT_SYMBOL, 237), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - - # Node 187 - (2, HUFFMAN_EMIT_SYMBOL, 199), - (9, HUFFMAN_EMIT_SYMBOL, 199), - (23, HUFFMAN_EMIT_SYMBOL, 199), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (2, HUFFMAN_EMIT_SYMBOL, 207), - (9, HUFFMAN_EMIT_SYMBOL, 207), - (23, HUFFMAN_EMIT_SYMBOL, 207), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - (2, HUFFMAN_EMIT_SYMBOL, 234), - (9, HUFFMAN_EMIT_SYMBOL, 234), - (23, HUFFMAN_EMIT_SYMBOL, 234), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (2, HUFFMAN_EMIT_SYMBOL, 235), - (9, HUFFMAN_EMIT_SYMBOL, 235), - (23, HUFFMAN_EMIT_SYMBOL, 235), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 188 - (3, HUFFMAN_EMIT_SYMBOL, 199), - (6, HUFFMAN_EMIT_SYMBOL, 199), - (10, HUFFMAN_EMIT_SYMBOL, 199), - (15, HUFFMAN_EMIT_SYMBOL, 199), - (24, HUFFMAN_EMIT_SYMBOL, 199), - (31, HUFFMAN_EMIT_SYMBOL, 199), - (41, HUFFMAN_EMIT_SYMBOL, 199), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (3, HUFFMAN_EMIT_SYMBOL, 207), - (6, HUFFMAN_EMIT_SYMBOL, 207), - (10, HUFFMAN_EMIT_SYMBOL, 207), - (15, HUFFMAN_EMIT_SYMBOL, 207), - (24, HUFFMAN_EMIT_SYMBOL, 207), - (31, HUFFMAN_EMIT_SYMBOL, 207), - (41, HUFFMAN_EMIT_SYMBOL, 207), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - - # Node 189 - (3, HUFFMAN_EMIT_SYMBOL, 234), - (6, HUFFMAN_EMIT_SYMBOL, 234), - (10, HUFFMAN_EMIT_SYMBOL, 234), - (15, HUFFMAN_EMIT_SYMBOL, 234), - (24, HUFFMAN_EMIT_SYMBOL, 234), - (31, HUFFMAN_EMIT_SYMBOL, 234), - (41, HUFFMAN_EMIT_SYMBOL, 234), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (3, HUFFMAN_EMIT_SYMBOL, 235), - (6, HUFFMAN_EMIT_SYMBOL, 235), - (10, HUFFMAN_EMIT_SYMBOL, 235), - (15, HUFFMAN_EMIT_SYMBOL, 235), - (24, HUFFMAN_EMIT_SYMBOL, 235), - (31, HUFFMAN_EMIT_SYMBOL, 235), - (41, HUFFMAN_EMIT_SYMBOL, 235), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 190 - (194, 0, 0), - (195, 0, 0), - (197, 0, 0), - (198, 0, 0), - (201, 0, 0), - (202, 0, 0), - (204, 0, 0), - (205, 0, 0), - (210, 0, 0), - (213, 0, 0), - (217, 0, 0), - (220, 0, 0), - (225, 0, 0), - (231, 0, 0), - (239, 0, 0), - (246, 0, 0), - - # Node 191 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (206, 0, 0), - - # Node 192 - (1, HUFFMAN_EMIT_SYMBOL, 192), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (1, HUFFMAN_EMIT_SYMBOL, 193), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - (1, HUFFMAN_EMIT_SYMBOL, 200), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (1, HUFFMAN_EMIT_SYMBOL, 201), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - (1, HUFFMAN_EMIT_SYMBOL, 202), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (1, HUFFMAN_EMIT_SYMBOL, 205), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - (1, HUFFMAN_EMIT_SYMBOL, 210), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (1, HUFFMAN_EMIT_SYMBOL, 213), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - - # Node 193 - (2, HUFFMAN_EMIT_SYMBOL, 192), - (9, HUFFMAN_EMIT_SYMBOL, 192), - (23, HUFFMAN_EMIT_SYMBOL, 192), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (2, HUFFMAN_EMIT_SYMBOL, 193), - (9, HUFFMAN_EMIT_SYMBOL, 193), - (23, HUFFMAN_EMIT_SYMBOL, 193), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - (2, HUFFMAN_EMIT_SYMBOL, 200), - (9, HUFFMAN_EMIT_SYMBOL, 200), - (23, HUFFMAN_EMIT_SYMBOL, 200), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (2, HUFFMAN_EMIT_SYMBOL, 201), - (9, HUFFMAN_EMIT_SYMBOL, 201), - (23, HUFFMAN_EMIT_SYMBOL, 201), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - - # Node 194 - (3, HUFFMAN_EMIT_SYMBOL, 192), - (6, HUFFMAN_EMIT_SYMBOL, 192), - (10, HUFFMAN_EMIT_SYMBOL, 192), - (15, HUFFMAN_EMIT_SYMBOL, 192), - (24, HUFFMAN_EMIT_SYMBOL, 192), - (31, HUFFMAN_EMIT_SYMBOL, 192), - (41, HUFFMAN_EMIT_SYMBOL, 192), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (3, HUFFMAN_EMIT_SYMBOL, 193), - (6, HUFFMAN_EMIT_SYMBOL, 193), - (10, HUFFMAN_EMIT_SYMBOL, 193), - (15, HUFFMAN_EMIT_SYMBOL, 193), - (24, HUFFMAN_EMIT_SYMBOL, 193), - (31, HUFFMAN_EMIT_SYMBOL, 193), - (41, HUFFMAN_EMIT_SYMBOL, 193), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - - # Node 195 - (3, HUFFMAN_EMIT_SYMBOL, 200), - (6, HUFFMAN_EMIT_SYMBOL, 200), - (10, HUFFMAN_EMIT_SYMBOL, 200), - (15, HUFFMAN_EMIT_SYMBOL, 200), - (24, HUFFMAN_EMIT_SYMBOL, 200), - (31, HUFFMAN_EMIT_SYMBOL, 200), - (41, HUFFMAN_EMIT_SYMBOL, 200), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (3, HUFFMAN_EMIT_SYMBOL, 201), - (6, HUFFMAN_EMIT_SYMBOL, 201), - (10, HUFFMAN_EMIT_SYMBOL, 201), - (15, HUFFMAN_EMIT_SYMBOL, 201), - (24, HUFFMAN_EMIT_SYMBOL, 201), - (31, HUFFMAN_EMIT_SYMBOL, 201), - (41, HUFFMAN_EMIT_SYMBOL, 201), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - - # Node 196 - (2, HUFFMAN_EMIT_SYMBOL, 202), - (9, HUFFMAN_EMIT_SYMBOL, 202), - (23, HUFFMAN_EMIT_SYMBOL, 202), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (2, HUFFMAN_EMIT_SYMBOL, 205), - (9, HUFFMAN_EMIT_SYMBOL, 205), - (23, HUFFMAN_EMIT_SYMBOL, 205), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - (2, HUFFMAN_EMIT_SYMBOL, 210), - (9, HUFFMAN_EMIT_SYMBOL, 210), - (23, HUFFMAN_EMIT_SYMBOL, 210), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (2, HUFFMAN_EMIT_SYMBOL, 213), - (9, HUFFMAN_EMIT_SYMBOL, 213), - (23, HUFFMAN_EMIT_SYMBOL, 213), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - - # Node 197 - (3, HUFFMAN_EMIT_SYMBOL, 202), - (6, HUFFMAN_EMIT_SYMBOL, 202), - (10, HUFFMAN_EMIT_SYMBOL, 202), - (15, HUFFMAN_EMIT_SYMBOL, 202), - (24, HUFFMAN_EMIT_SYMBOL, 202), - (31, HUFFMAN_EMIT_SYMBOL, 202), - (41, HUFFMAN_EMIT_SYMBOL, 202), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (3, HUFFMAN_EMIT_SYMBOL, 205), - (6, HUFFMAN_EMIT_SYMBOL, 205), - (10, HUFFMAN_EMIT_SYMBOL, 205), - (15, HUFFMAN_EMIT_SYMBOL, 205), - (24, HUFFMAN_EMIT_SYMBOL, 205), - (31, HUFFMAN_EMIT_SYMBOL, 205), - (41, HUFFMAN_EMIT_SYMBOL, 205), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - - # Node 198 - (3, HUFFMAN_EMIT_SYMBOL, 210), - (6, HUFFMAN_EMIT_SYMBOL, 210), - (10, HUFFMAN_EMIT_SYMBOL, 210), - (15, HUFFMAN_EMIT_SYMBOL, 210), - (24, HUFFMAN_EMIT_SYMBOL, 210), - (31, HUFFMAN_EMIT_SYMBOL, 210), - (41, HUFFMAN_EMIT_SYMBOL, 210), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (3, HUFFMAN_EMIT_SYMBOL, 213), - (6, HUFFMAN_EMIT_SYMBOL, 213), - (10, HUFFMAN_EMIT_SYMBOL, 213), - (15, HUFFMAN_EMIT_SYMBOL, 213), - (24, HUFFMAN_EMIT_SYMBOL, 213), - (31, HUFFMAN_EMIT_SYMBOL, 213), - (41, HUFFMAN_EMIT_SYMBOL, 213), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - - # Node 199 - (1, HUFFMAN_EMIT_SYMBOL, 218), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (1, HUFFMAN_EMIT_SYMBOL, 219), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - (1, HUFFMAN_EMIT_SYMBOL, 238), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (1, HUFFMAN_EMIT_SYMBOL, 240), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - (1, HUFFMAN_EMIT_SYMBOL, 242), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (1, HUFFMAN_EMIT_SYMBOL, 243), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - (1, HUFFMAN_EMIT_SYMBOL, 255), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 200 - (2, HUFFMAN_EMIT_SYMBOL, 218), - (9, HUFFMAN_EMIT_SYMBOL, 218), - (23, HUFFMAN_EMIT_SYMBOL, 218), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (2, HUFFMAN_EMIT_SYMBOL, 219), - (9, HUFFMAN_EMIT_SYMBOL, 219), - (23, HUFFMAN_EMIT_SYMBOL, 219), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - (2, HUFFMAN_EMIT_SYMBOL, 238), - (9, HUFFMAN_EMIT_SYMBOL, 238), - (23, HUFFMAN_EMIT_SYMBOL, 238), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (2, HUFFMAN_EMIT_SYMBOL, 240), - (9, HUFFMAN_EMIT_SYMBOL, 240), - (23, HUFFMAN_EMIT_SYMBOL, 240), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - - # Node 201 - (3, HUFFMAN_EMIT_SYMBOL, 218), - (6, HUFFMAN_EMIT_SYMBOL, 218), - (10, HUFFMAN_EMIT_SYMBOL, 218), - (15, HUFFMAN_EMIT_SYMBOL, 218), - (24, HUFFMAN_EMIT_SYMBOL, 218), - (31, HUFFMAN_EMIT_SYMBOL, 218), - (41, HUFFMAN_EMIT_SYMBOL, 218), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (3, HUFFMAN_EMIT_SYMBOL, 219), - (6, HUFFMAN_EMIT_SYMBOL, 219), - (10, HUFFMAN_EMIT_SYMBOL, 219), - (15, HUFFMAN_EMIT_SYMBOL, 219), - (24, HUFFMAN_EMIT_SYMBOL, 219), - (31, HUFFMAN_EMIT_SYMBOL, 219), - (41, HUFFMAN_EMIT_SYMBOL, 219), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - - # Node 202 - (3, HUFFMAN_EMIT_SYMBOL, 238), - (6, HUFFMAN_EMIT_SYMBOL, 238), - (10, HUFFMAN_EMIT_SYMBOL, 238), - (15, HUFFMAN_EMIT_SYMBOL, 238), - (24, HUFFMAN_EMIT_SYMBOL, 238), - (31, HUFFMAN_EMIT_SYMBOL, 238), - (41, HUFFMAN_EMIT_SYMBOL, 238), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (3, HUFFMAN_EMIT_SYMBOL, 240), - (6, HUFFMAN_EMIT_SYMBOL, 240), - (10, HUFFMAN_EMIT_SYMBOL, 240), - (15, HUFFMAN_EMIT_SYMBOL, 240), - (24, HUFFMAN_EMIT_SYMBOL, 240), - (31, HUFFMAN_EMIT_SYMBOL, 240), - (41, HUFFMAN_EMIT_SYMBOL, 240), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - - # Node 203 - (2, HUFFMAN_EMIT_SYMBOL, 242), - (9, HUFFMAN_EMIT_SYMBOL, 242), - (23, HUFFMAN_EMIT_SYMBOL, 242), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (2, HUFFMAN_EMIT_SYMBOL, 243), - (9, HUFFMAN_EMIT_SYMBOL, 243), - (23, HUFFMAN_EMIT_SYMBOL, 243), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - (2, HUFFMAN_EMIT_SYMBOL, 255), - (9, HUFFMAN_EMIT_SYMBOL, 255), - (23, HUFFMAN_EMIT_SYMBOL, 255), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (1, HUFFMAN_EMIT_SYMBOL, 203), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (1, HUFFMAN_EMIT_SYMBOL, 204), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 204 - (3, HUFFMAN_EMIT_SYMBOL, 242), - (6, HUFFMAN_EMIT_SYMBOL, 242), - (10, HUFFMAN_EMIT_SYMBOL, 242), - (15, HUFFMAN_EMIT_SYMBOL, 242), - (24, HUFFMAN_EMIT_SYMBOL, 242), - (31, HUFFMAN_EMIT_SYMBOL, 242), - (41, HUFFMAN_EMIT_SYMBOL, 242), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (3, HUFFMAN_EMIT_SYMBOL, 243), - (6, HUFFMAN_EMIT_SYMBOL, 243), - (10, HUFFMAN_EMIT_SYMBOL, 243), - (15, HUFFMAN_EMIT_SYMBOL, 243), - (24, HUFFMAN_EMIT_SYMBOL, 243), - (31, HUFFMAN_EMIT_SYMBOL, 243), - (41, HUFFMAN_EMIT_SYMBOL, 243), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - - # Node 205 - (3, HUFFMAN_EMIT_SYMBOL, 255), - (6, HUFFMAN_EMIT_SYMBOL, 255), - (10, HUFFMAN_EMIT_SYMBOL, 255), - (15, HUFFMAN_EMIT_SYMBOL, 255), - (24, HUFFMAN_EMIT_SYMBOL, 255), - (31, HUFFMAN_EMIT_SYMBOL, 255), - (41, HUFFMAN_EMIT_SYMBOL, 255), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (2, HUFFMAN_EMIT_SYMBOL, 203), - (9, HUFFMAN_EMIT_SYMBOL, 203), - (23, HUFFMAN_EMIT_SYMBOL, 203), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (2, HUFFMAN_EMIT_SYMBOL, 204), - (9, HUFFMAN_EMIT_SYMBOL, 204), - (23, HUFFMAN_EMIT_SYMBOL, 204), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 206 - (3, HUFFMAN_EMIT_SYMBOL, 203), - (6, HUFFMAN_EMIT_SYMBOL, 203), - (10, HUFFMAN_EMIT_SYMBOL, 203), - (15, HUFFMAN_EMIT_SYMBOL, 203), - (24, HUFFMAN_EMIT_SYMBOL, 203), - (31, HUFFMAN_EMIT_SYMBOL, 203), - (41, HUFFMAN_EMIT_SYMBOL, 203), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (3, HUFFMAN_EMIT_SYMBOL, 204), - (6, HUFFMAN_EMIT_SYMBOL, 204), - (10, HUFFMAN_EMIT_SYMBOL, 204), - (15, HUFFMAN_EMIT_SYMBOL, 204), - (24, HUFFMAN_EMIT_SYMBOL, 204), - (31, HUFFMAN_EMIT_SYMBOL, 204), - (41, HUFFMAN_EMIT_SYMBOL, 204), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 207 - (211, 0, 0), - (212, 0, 0), - (214, 0, 0), - (215, 0, 0), - (218, 0, 0), - (219, 0, 0), - (221, 0, 0), - (222, 0, 0), - (226, 0, 0), - (228, 0, 0), - (232, 0, 0), - (235, 0, 0), - (240, 0, 0), - (243, 0, 0), - (247, 0, 0), - (250, 0, 0), - - # Node 208 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 209 - (1, HUFFMAN_EMIT_SYMBOL, 211), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (1, HUFFMAN_EMIT_SYMBOL, 212), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - (1, HUFFMAN_EMIT_SYMBOL, 214), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (1, HUFFMAN_EMIT_SYMBOL, 221), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - (1, HUFFMAN_EMIT_SYMBOL, 222), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (1, HUFFMAN_EMIT_SYMBOL, 223), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - (1, HUFFMAN_EMIT_SYMBOL, 241), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (1, HUFFMAN_EMIT_SYMBOL, 244), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - - # Node 210 - (2, HUFFMAN_EMIT_SYMBOL, 211), - (9, HUFFMAN_EMIT_SYMBOL, 211), - (23, HUFFMAN_EMIT_SYMBOL, 211), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (2, HUFFMAN_EMIT_SYMBOL, 212), - (9, HUFFMAN_EMIT_SYMBOL, 212), - (23, HUFFMAN_EMIT_SYMBOL, 212), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - (2, HUFFMAN_EMIT_SYMBOL, 214), - (9, HUFFMAN_EMIT_SYMBOL, 214), - (23, HUFFMAN_EMIT_SYMBOL, 214), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (2, HUFFMAN_EMIT_SYMBOL, 221), - (9, HUFFMAN_EMIT_SYMBOL, 221), - (23, HUFFMAN_EMIT_SYMBOL, 221), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - - # Node 211 - (3, HUFFMAN_EMIT_SYMBOL, 211), - (6, HUFFMAN_EMIT_SYMBOL, 211), - (10, HUFFMAN_EMIT_SYMBOL, 211), - (15, HUFFMAN_EMIT_SYMBOL, 211), - (24, HUFFMAN_EMIT_SYMBOL, 211), - (31, HUFFMAN_EMIT_SYMBOL, 211), - (41, HUFFMAN_EMIT_SYMBOL, 211), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (3, HUFFMAN_EMIT_SYMBOL, 212), - (6, HUFFMAN_EMIT_SYMBOL, 212), - (10, HUFFMAN_EMIT_SYMBOL, 212), - (15, HUFFMAN_EMIT_SYMBOL, 212), - (24, HUFFMAN_EMIT_SYMBOL, 212), - (31, HUFFMAN_EMIT_SYMBOL, 212), - (41, HUFFMAN_EMIT_SYMBOL, 212), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - - # Node 212 - (3, HUFFMAN_EMIT_SYMBOL, 214), - (6, HUFFMAN_EMIT_SYMBOL, 214), - (10, HUFFMAN_EMIT_SYMBOL, 214), - (15, HUFFMAN_EMIT_SYMBOL, 214), - (24, HUFFMAN_EMIT_SYMBOL, 214), - (31, HUFFMAN_EMIT_SYMBOL, 214), - (41, HUFFMAN_EMIT_SYMBOL, 214), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (3, HUFFMAN_EMIT_SYMBOL, 221), - (6, HUFFMAN_EMIT_SYMBOL, 221), - (10, HUFFMAN_EMIT_SYMBOL, 221), - (15, HUFFMAN_EMIT_SYMBOL, 221), - (24, HUFFMAN_EMIT_SYMBOL, 221), - (31, HUFFMAN_EMIT_SYMBOL, 221), - (41, HUFFMAN_EMIT_SYMBOL, 221), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - - # Node 213 - (2, HUFFMAN_EMIT_SYMBOL, 222), - (9, HUFFMAN_EMIT_SYMBOL, 222), - (23, HUFFMAN_EMIT_SYMBOL, 222), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (2, HUFFMAN_EMIT_SYMBOL, 223), - (9, HUFFMAN_EMIT_SYMBOL, 223), - (23, HUFFMAN_EMIT_SYMBOL, 223), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - (2, HUFFMAN_EMIT_SYMBOL, 241), - (9, HUFFMAN_EMIT_SYMBOL, 241), - (23, HUFFMAN_EMIT_SYMBOL, 241), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (2, HUFFMAN_EMIT_SYMBOL, 244), - (9, HUFFMAN_EMIT_SYMBOL, 244), - (23, HUFFMAN_EMIT_SYMBOL, 244), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - - # Node 214 - (3, HUFFMAN_EMIT_SYMBOL, 222), - (6, HUFFMAN_EMIT_SYMBOL, 222), - (10, HUFFMAN_EMIT_SYMBOL, 222), - (15, HUFFMAN_EMIT_SYMBOL, 222), - (24, HUFFMAN_EMIT_SYMBOL, 222), - (31, HUFFMAN_EMIT_SYMBOL, 222), - (41, HUFFMAN_EMIT_SYMBOL, 222), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (3, HUFFMAN_EMIT_SYMBOL, 223), - (6, HUFFMAN_EMIT_SYMBOL, 223), - (10, HUFFMAN_EMIT_SYMBOL, 223), - (15, HUFFMAN_EMIT_SYMBOL, 223), - (24, HUFFMAN_EMIT_SYMBOL, 223), - (31, HUFFMAN_EMIT_SYMBOL, 223), - (41, HUFFMAN_EMIT_SYMBOL, 223), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - - # Node 215 - (3, HUFFMAN_EMIT_SYMBOL, 241), - (6, HUFFMAN_EMIT_SYMBOL, 241), - (10, HUFFMAN_EMIT_SYMBOL, 241), - (15, HUFFMAN_EMIT_SYMBOL, 241), - (24, HUFFMAN_EMIT_SYMBOL, 241), - (31, HUFFMAN_EMIT_SYMBOL, 241), - (41, HUFFMAN_EMIT_SYMBOL, 241), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (3, HUFFMAN_EMIT_SYMBOL, 244), - (6, HUFFMAN_EMIT_SYMBOL, 244), - (10, HUFFMAN_EMIT_SYMBOL, 244), - (15, HUFFMAN_EMIT_SYMBOL, 244), - (24, HUFFMAN_EMIT_SYMBOL, 244), - (31, HUFFMAN_EMIT_SYMBOL, 244), - (41, HUFFMAN_EMIT_SYMBOL, 244), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - - # Node 216 - (1, HUFFMAN_EMIT_SYMBOL, 245), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (1, HUFFMAN_EMIT_SYMBOL, 246), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - (1, HUFFMAN_EMIT_SYMBOL, 247), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (1, HUFFMAN_EMIT_SYMBOL, 248), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - (1, HUFFMAN_EMIT_SYMBOL, 250), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (1, HUFFMAN_EMIT_SYMBOL, 251), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - (1, HUFFMAN_EMIT_SYMBOL, 252), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (1, HUFFMAN_EMIT_SYMBOL, 253), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 217 - (2, HUFFMAN_EMIT_SYMBOL, 245), - (9, HUFFMAN_EMIT_SYMBOL, 245), - (23, HUFFMAN_EMIT_SYMBOL, 245), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (2, HUFFMAN_EMIT_SYMBOL, 246), - (9, HUFFMAN_EMIT_SYMBOL, 246), - (23, HUFFMAN_EMIT_SYMBOL, 246), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - (2, HUFFMAN_EMIT_SYMBOL, 247), - (9, HUFFMAN_EMIT_SYMBOL, 247), - (23, HUFFMAN_EMIT_SYMBOL, 247), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (2, HUFFMAN_EMIT_SYMBOL, 248), - (9, HUFFMAN_EMIT_SYMBOL, 248), - (23, HUFFMAN_EMIT_SYMBOL, 248), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - - # Node 218 - (3, HUFFMAN_EMIT_SYMBOL, 245), - (6, HUFFMAN_EMIT_SYMBOL, 245), - (10, HUFFMAN_EMIT_SYMBOL, 245), - (15, HUFFMAN_EMIT_SYMBOL, 245), - (24, HUFFMAN_EMIT_SYMBOL, 245), - (31, HUFFMAN_EMIT_SYMBOL, 245), - (41, HUFFMAN_EMIT_SYMBOL, 245), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (3, HUFFMAN_EMIT_SYMBOL, 246), - (6, HUFFMAN_EMIT_SYMBOL, 246), - (10, HUFFMAN_EMIT_SYMBOL, 246), - (15, HUFFMAN_EMIT_SYMBOL, 246), - (24, HUFFMAN_EMIT_SYMBOL, 246), - (31, HUFFMAN_EMIT_SYMBOL, 246), - (41, HUFFMAN_EMIT_SYMBOL, 246), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - - # Node 219 - (3, HUFFMAN_EMIT_SYMBOL, 247), - (6, HUFFMAN_EMIT_SYMBOL, 247), - (10, HUFFMAN_EMIT_SYMBOL, 247), - (15, HUFFMAN_EMIT_SYMBOL, 247), - (24, HUFFMAN_EMIT_SYMBOL, 247), - (31, HUFFMAN_EMIT_SYMBOL, 247), - (41, HUFFMAN_EMIT_SYMBOL, 247), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (3, HUFFMAN_EMIT_SYMBOL, 248), - (6, HUFFMAN_EMIT_SYMBOL, 248), - (10, HUFFMAN_EMIT_SYMBOL, 248), - (15, HUFFMAN_EMIT_SYMBOL, 248), - (24, HUFFMAN_EMIT_SYMBOL, 248), - (31, HUFFMAN_EMIT_SYMBOL, 248), - (41, HUFFMAN_EMIT_SYMBOL, 248), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - - # Node 220 - (2, HUFFMAN_EMIT_SYMBOL, 250), - (9, HUFFMAN_EMIT_SYMBOL, 250), - (23, HUFFMAN_EMIT_SYMBOL, 250), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (2, HUFFMAN_EMIT_SYMBOL, 251), - (9, HUFFMAN_EMIT_SYMBOL, 251), - (23, HUFFMAN_EMIT_SYMBOL, 251), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - (2, HUFFMAN_EMIT_SYMBOL, 252), - (9, HUFFMAN_EMIT_SYMBOL, 252), - (23, HUFFMAN_EMIT_SYMBOL, 252), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (2, HUFFMAN_EMIT_SYMBOL, 253), - (9, HUFFMAN_EMIT_SYMBOL, 253), - (23, HUFFMAN_EMIT_SYMBOL, 253), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 221 - (3, HUFFMAN_EMIT_SYMBOL, 250), - (6, HUFFMAN_EMIT_SYMBOL, 250), - (10, HUFFMAN_EMIT_SYMBOL, 250), - (15, HUFFMAN_EMIT_SYMBOL, 250), - (24, HUFFMAN_EMIT_SYMBOL, 250), - (31, HUFFMAN_EMIT_SYMBOL, 250), - (41, HUFFMAN_EMIT_SYMBOL, 250), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (3, HUFFMAN_EMIT_SYMBOL, 251), - (6, HUFFMAN_EMIT_SYMBOL, 251), - (10, HUFFMAN_EMIT_SYMBOL, 251), - (15, HUFFMAN_EMIT_SYMBOL, 251), - (24, HUFFMAN_EMIT_SYMBOL, 251), - (31, HUFFMAN_EMIT_SYMBOL, 251), - (41, HUFFMAN_EMIT_SYMBOL, 251), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - - # Node 222 - (3, HUFFMAN_EMIT_SYMBOL, 252), - (6, HUFFMAN_EMIT_SYMBOL, 252), - (10, HUFFMAN_EMIT_SYMBOL, 252), - (15, HUFFMAN_EMIT_SYMBOL, 252), - (24, HUFFMAN_EMIT_SYMBOL, 252), - (31, HUFFMAN_EMIT_SYMBOL, 252), - (41, HUFFMAN_EMIT_SYMBOL, 252), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (3, HUFFMAN_EMIT_SYMBOL, 253), - (6, HUFFMAN_EMIT_SYMBOL, 253), - (10, HUFFMAN_EMIT_SYMBOL, 253), - (15, HUFFMAN_EMIT_SYMBOL, 253), - (24, HUFFMAN_EMIT_SYMBOL, 253), - (31, HUFFMAN_EMIT_SYMBOL, 253), - (41, HUFFMAN_EMIT_SYMBOL, 253), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 223 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (227, 0, 0), - (229, 0, 0), - (230, 0, 0), - (233, 0, 0), - (234, 0, 0), - (236, 0, 0), - (237, 0, 0), - (241, 0, 0), - (242, 0, 0), - (244, 0, 0), - (245, 0, 0), - (248, 0, 0), - (249, 0, 0), - (251, 0, 0), - (252, 0, 0), - - # Node 224 - (1, HUFFMAN_EMIT_SYMBOL, 254), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 225 - (2, HUFFMAN_EMIT_SYMBOL, 254), - (9, HUFFMAN_EMIT_SYMBOL, 254), - (23, HUFFMAN_EMIT_SYMBOL, 254), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (1, HUFFMAN_EMIT_SYMBOL, 2), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (1, HUFFMAN_EMIT_SYMBOL, 3), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - (1, HUFFMAN_EMIT_SYMBOL, 4), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (1, HUFFMAN_EMIT_SYMBOL, 5), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - (1, HUFFMAN_EMIT_SYMBOL, 6), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (1, HUFFMAN_EMIT_SYMBOL, 7), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - - # Node 226 - (3, HUFFMAN_EMIT_SYMBOL, 254), - (6, HUFFMAN_EMIT_SYMBOL, 254), - (10, HUFFMAN_EMIT_SYMBOL, 254), - (15, HUFFMAN_EMIT_SYMBOL, 254), - (24, HUFFMAN_EMIT_SYMBOL, 254), - (31, HUFFMAN_EMIT_SYMBOL, 254), - (41, HUFFMAN_EMIT_SYMBOL, 254), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (2, HUFFMAN_EMIT_SYMBOL, 2), - (9, HUFFMAN_EMIT_SYMBOL, 2), - (23, HUFFMAN_EMIT_SYMBOL, 2), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (2, HUFFMAN_EMIT_SYMBOL, 3), - (9, HUFFMAN_EMIT_SYMBOL, 3), - (23, HUFFMAN_EMIT_SYMBOL, 3), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - - # Node 227 - (3, HUFFMAN_EMIT_SYMBOL, 2), - (6, HUFFMAN_EMIT_SYMBOL, 2), - (10, HUFFMAN_EMIT_SYMBOL, 2), - (15, HUFFMAN_EMIT_SYMBOL, 2), - (24, HUFFMAN_EMIT_SYMBOL, 2), - (31, HUFFMAN_EMIT_SYMBOL, 2), - (41, HUFFMAN_EMIT_SYMBOL, 2), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (3, HUFFMAN_EMIT_SYMBOL, 3), - (6, HUFFMAN_EMIT_SYMBOL, 3), - (10, HUFFMAN_EMIT_SYMBOL, 3), - (15, HUFFMAN_EMIT_SYMBOL, 3), - (24, HUFFMAN_EMIT_SYMBOL, 3), - (31, HUFFMAN_EMIT_SYMBOL, 3), - (41, HUFFMAN_EMIT_SYMBOL, 3), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - - # Node 228 - (2, HUFFMAN_EMIT_SYMBOL, 4), - (9, HUFFMAN_EMIT_SYMBOL, 4), - (23, HUFFMAN_EMIT_SYMBOL, 4), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (2, HUFFMAN_EMIT_SYMBOL, 5), - (9, HUFFMAN_EMIT_SYMBOL, 5), - (23, HUFFMAN_EMIT_SYMBOL, 5), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - (2, HUFFMAN_EMIT_SYMBOL, 6), - (9, HUFFMAN_EMIT_SYMBOL, 6), - (23, HUFFMAN_EMIT_SYMBOL, 6), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (2, HUFFMAN_EMIT_SYMBOL, 7), - (9, HUFFMAN_EMIT_SYMBOL, 7), - (23, HUFFMAN_EMIT_SYMBOL, 7), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - - # Node 229 - (3, HUFFMAN_EMIT_SYMBOL, 4), - (6, HUFFMAN_EMIT_SYMBOL, 4), - (10, HUFFMAN_EMIT_SYMBOL, 4), - (15, HUFFMAN_EMIT_SYMBOL, 4), - (24, HUFFMAN_EMIT_SYMBOL, 4), - (31, HUFFMAN_EMIT_SYMBOL, 4), - (41, HUFFMAN_EMIT_SYMBOL, 4), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (3, HUFFMAN_EMIT_SYMBOL, 5), - (6, HUFFMAN_EMIT_SYMBOL, 5), - (10, HUFFMAN_EMIT_SYMBOL, 5), - (15, HUFFMAN_EMIT_SYMBOL, 5), - (24, HUFFMAN_EMIT_SYMBOL, 5), - (31, HUFFMAN_EMIT_SYMBOL, 5), - (41, HUFFMAN_EMIT_SYMBOL, 5), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - - # Node 230 - (3, HUFFMAN_EMIT_SYMBOL, 6), - (6, HUFFMAN_EMIT_SYMBOL, 6), - (10, HUFFMAN_EMIT_SYMBOL, 6), - (15, HUFFMAN_EMIT_SYMBOL, 6), - (24, HUFFMAN_EMIT_SYMBOL, 6), - (31, HUFFMAN_EMIT_SYMBOL, 6), - (41, HUFFMAN_EMIT_SYMBOL, 6), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (3, HUFFMAN_EMIT_SYMBOL, 7), - (6, HUFFMAN_EMIT_SYMBOL, 7), - (10, HUFFMAN_EMIT_SYMBOL, 7), - (15, HUFFMAN_EMIT_SYMBOL, 7), - (24, HUFFMAN_EMIT_SYMBOL, 7), - (31, HUFFMAN_EMIT_SYMBOL, 7), - (41, HUFFMAN_EMIT_SYMBOL, 7), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - - # Node 231 - (1, HUFFMAN_EMIT_SYMBOL, 8), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (1, HUFFMAN_EMIT_SYMBOL, 11), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - (1, HUFFMAN_EMIT_SYMBOL, 12), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (1, HUFFMAN_EMIT_SYMBOL, 14), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - (1, HUFFMAN_EMIT_SYMBOL, 15), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (1, HUFFMAN_EMIT_SYMBOL, 16), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - (1, HUFFMAN_EMIT_SYMBOL, 17), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (1, HUFFMAN_EMIT_SYMBOL, 18), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 232 - (2, HUFFMAN_EMIT_SYMBOL, 8), - (9, HUFFMAN_EMIT_SYMBOL, 8), - (23, HUFFMAN_EMIT_SYMBOL, 8), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (2, HUFFMAN_EMIT_SYMBOL, 11), - (9, HUFFMAN_EMIT_SYMBOL, 11), - (23, HUFFMAN_EMIT_SYMBOL, 11), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - (2, HUFFMAN_EMIT_SYMBOL, 12), - (9, HUFFMAN_EMIT_SYMBOL, 12), - (23, HUFFMAN_EMIT_SYMBOL, 12), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (2, HUFFMAN_EMIT_SYMBOL, 14), - (9, HUFFMAN_EMIT_SYMBOL, 14), - (23, HUFFMAN_EMIT_SYMBOL, 14), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - - # Node 233 - (3, HUFFMAN_EMIT_SYMBOL, 8), - (6, HUFFMAN_EMIT_SYMBOL, 8), - (10, HUFFMAN_EMIT_SYMBOL, 8), - (15, HUFFMAN_EMIT_SYMBOL, 8), - (24, HUFFMAN_EMIT_SYMBOL, 8), - (31, HUFFMAN_EMIT_SYMBOL, 8), - (41, HUFFMAN_EMIT_SYMBOL, 8), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (3, HUFFMAN_EMIT_SYMBOL, 11), - (6, HUFFMAN_EMIT_SYMBOL, 11), - (10, HUFFMAN_EMIT_SYMBOL, 11), - (15, HUFFMAN_EMIT_SYMBOL, 11), - (24, HUFFMAN_EMIT_SYMBOL, 11), - (31, HUFFMAN_EMIT_SYMBOL, 11), - (41, HUFFMAN_EMIT_SYMBOL, 11), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - - # Node 234 - (3, HUFFMAN_EMIT_SYMBOL, 12), - (6, HUFFMAN_EMIT_SYMBOL, 12), - (10, HUFFMAN_EMIT_SYMBOL, 12), - (15, HUFFMAN_EMIT_SYMBOL, 12), - (24, HUFFMAN_EMIT_SYMBOL, 12), - (31, HUFFMAN_EMIT_SYMBOL, 12), - (41, HUFFMAN_EMIT_SYMBOL, 12), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (3, HUFFMAN_EMIT_SYMBOL, 14), - (6, HUFFMAN_EMIT_SYMBOL, 14), - (10, HUFFMAN_EMIT_SYMBOL, 14), - (15, HUFFMAN_EMIT_SYMBOL, 14), - (24, HUFFMAN_EMIT_SYMBOL, 14), - (31, HUFFMAN_EMIT_SYMBOL, 14), - (41, HUFFMAN_EMIT_SYMBOL, 14), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - - # Node 235 - (2, HUFFMAN_EMIT_SYMBOL, 15), - (9, HUFFMAN_EMIT_SYMBOL, 15), - (23, HUFFMAN_EMIT_SYMBOL, 15), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (2, HUFFMAN_EMIT_SYMBOL, 16), - (9, HUFFMAN_EMIT_SYMBOL, 16), - (23, HUFFMAN_EMIT_SYMBOL, 16), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - (2, HUFFMAN_EMIT_SYMBOL, 17), - (9, HUFFMAN_EMIT_SYMBOL, 17), - (23, HUFFMAN_EMIT_SYMBOL, 17), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (2, HUFFMAN_EMIT_SYMBOL, 18), - (9, HUFFMAN_EMIT_SYMBOL, 18), - (23, HUFFMAN_EMIT_SYMBOL, 18), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 236 - (3, HUFFMAN_EMIT_SYMBOL, 15), - (6, HUFFMAN_EMIT_SYMBOL, 15), - (10, HUFFMAN_EMIT_SYMBOL, 15), - (15, HUFFMAN_EMIT_SYMBOL, 15), - (24, HUFFMAN_EMIT_SYMBOL, 15), - (31, HUFFMAN_EMIT_SYMBOL, 15), - (41, HUFFMAN_EMIT_SYMBOL, 15), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (3, HUFFMAN_EMIT_SYMBOL, 16), - (6, HUFFMAN_EMIT_SYMBOL, 16), - (10, HUFFMAN_EMIT_SYMBOL, 16), - (15, HUFFMAN_EMIT_SYMBOL, 16), - (24, HUFFMAN_EMIT_SYMBOL, 16), - (31, HUFFMAN_EMIT_SYMBOL, 16), - (41, HUFFMAN_EMIT_SYMBOL, 16), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - - # Node 237 - (3, HUFFMAN_EMIT_SYMBOL, 17), - (6, HUFFMAN_EMIT_SYMBOL, 17), - (10, HUFFMAN_EMIT_SYMBOL, 17), - (15, HUFFMAN_EMIT_SYMBOL, 17), - (24, HUFFMAN_EMIT_SYMBOL, 17), - (31, HUFFMAN_EMIT_SYMBOL, 17), - (41, HUFFMAN_EMIT_SYMBOL, 17), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (3, HUFFMAN_EMIT_SYMBOL, 18), - (6, HUFFMAN_EMIT_SYMBOL, 18), - (10, HUFFMAN_EMIT_SYMBOL, 18), - (15, HUFFMAN_EMIT_SYMBOL, 18), - (24, HUFFMAN_EMIT_SYMBOL, 18), - (31, HUFFMAN_EMIT_SYMBOL, 18), - (41, HUFFMAN_EMIT_SYMBOL, 18), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 238 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (253, 0, 0), - - # Node 239 - (1, HUFFMAN_EMIT_SYMBOL, 19), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (1, HUFFMAN_EMIT_SYMBOL, 20), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - (1, HUFFMAN_EMIT_SYMBOL, 21), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (1, HUFFMAN_EMIT_SYMBOL, 23), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - (1, HUFFMAN_EMIT_SYMBOL, 24), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (1, HUFFMAN_EMIT_SYMBOL, 25), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - (1, HUFFMAN_EMIT_SYMBOL, 26), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (1, HUFFMAN_EMIT_SYMBOL, 27), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - - # Node 240 - (2, HUFFMAN_EMIT_SYMBOL, 19), - (9, HUFFMAN_EMIT_SYMBOL, 19), - (23, HUFFMAN_EMIT_SYMBOL, 19), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (2, HUFFMAN_EMIT_SYMBOL, 20), - (9, HUFFMAN_EMIT_SYMBOL, 20), - (23, HUFFMAN_EMIT_SYMBOL, 20), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - (2, HUFFMAN_EMIT_SYMBOL, 21), - (9, HUFFMAN_EMIT_SYMBOL, 21), - (23, HUFFMAN_EMIT_SYMBOL, 21), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (2, HUFFMAN_EMIT_SYMBOL, 23), - (9, HUFFMAN_EMIT_SYMBOL, 23), - (23, HUFFMAN_EMIT_SYMBOL, 23), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - - # Node 241 - (3, HUFFMAN_EMIT_SYMBOL, 19), - (6, HUFFMAN_EMIT_SYMBOL, 19), - (10, HUFFMAN_EMIT_SYMBOL, 19), - (15, HUFFMAN_EMIT_SYMBOL, 19), - (24, HUFFMAN_EMIT_SYMBOL, 19), - (31, HUFFMAN_EMIT_SYMBOL, 19), - (41, HUFFMAN_EMIT_SYMBOL, 19), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (3, HUFFMAN_EMIT_SYMBOL, 20), - (6, HUFFMAN_EMIT_SYMBOL, 20), - (10, HUFFMAN_EMIT_SYMBOL, 20), - (15, HUFFMAN_EMIT_SYMBOL, 20), - (24, HUFFMAN_EMIT_SYMBOL, 20), - (31, HUFFMAN_EMIT_SYMBOL, 20), - (41, HUFFMAN_EMIT_SYMBOL, 20), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - - # Node 242 - (3, HUFFMAN_EMIT_SYMBOL, 21), - (6, HUFFMAN_EMIT_SYMBOL, 21), - (10, HUFFMAN_EMIT_SYMBOL, 21), - (15, HUFFMAN_EMIT_SYMBOL, 21), - (24, HUFFMAN_EMIT_SYMBOL, 21), - (31, HUFFMAN_EMIT_SYMBOL, 21), - (41, HUFFMAN_EMIT_SYMBOL, 21), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (3, HUFFMAN_EMIT_SYMBOL, 23), - (6, HUFFMAN_EMIT_SYMBOL, 23), - (10, HUFFMAN_EMIT_SYMBOL, 23), - (15, HUFFMAN_EMIT_SYMBOL, 23), - (24, HUFFMAN_EMIT_SYMBOL, 23), - (31, HUFFMAN_EMIT_SYMBOL, 23), - (41, HUFFMAN_EMIT_SYMBOL, 23), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - - # Node 243 - (2, HUFFMAN_EMIT_SYMBOL, 24), - (9, HUFFMAN_EMIT_SYMBOL, 24), - (23, HUFFMAN_EMIT_SYMBOL, 24), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (2, HUFFMAN_EMIT_SYMBOL, 25), - (9, HUFFMAN_EMIT_SYMBOL, 25), - (23, HUFFMAN_EMIT_SYMBOL, 25), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - (2, HUFFMAN_EMIT_SYMBOL, 26), - (9, HUFFMAN_EMIT_SYMBOL, 26), - (23, HUFFMAN_EMIT_SYMBOL, 26), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (2, HUFFMAN_EMIT_SYMBOL, 27), - (9, HUFFMAN_EMIT_SYMBOL, 27), - (23, HUFFMAN_EMIT_SYMBOL, 27), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - - # Node 244 - (3, HUFFMAN_EMIT_SYMBOL, 24), - (6, HUFFMAN_EMIT_SYMBOL, 24), - (10, HUFFMAN_EMIT_SYMBOL, 24), - (15, HUFFMAN_EMIT_SYMBOL, 24), - (24, HUFFMAN_EMIT_SYMBOL, 24), - (31, HUFFMAN_EMIT_SYMBOL, 24), - (41, HUFFMAN_EMIT_SYMBOL, 24), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (3, HUFFMAN_EMIT_SYMBOL, 25), - (6, HUFFMAN_EMIT_SYMBOL, 25), - (10, HUFFMAN_EMIT_SYMBOL, 25), - (15, HUFFMAN_EMIT_SYMBOL, 25), - (24, HUFFMAN_EMIT_SYMBOL, 25), - (31, HUFFMAN_EMIT_SYMBOL, 25), - (41, HUFFMAN_EMIT_SYMBOL, 25), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - - # Node 245 - (3, HUFFMAN_EMIT_SYMBOL, 26), - (6, HUFFMAN_EMIT_SYMBOL, 26), - (10, HUFFMAN_EMIT_SYMBOL, 26), - (15, HUFFMAN_EMIT_SYMBOL, 26), - (24, HUFFMAN_EMIT_SYMBOL, 26), - (31, HUFFMAN_EMIT_SYMBOL, 26), - (41, HUFFMAN_EMIT_SYMBOL, 26), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (3, HUFFMAN_EMIT_SYMBOL, 27), - (6, HUFFMAN_EMIT_SYMBOL, 27), - (10, HUFFMAN_EMIT_SYMBOL, 27), - (15, HUFFMAN_EMIT_SYMBOL, 27), - (24, HUFFMAN_EMIT_SYMBOL, 27), - (31, HUFFMAN_EMIT_SYMBOL, 27), - (41, HUFFMAN_EMIT_SYMBOL, 27), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - - # Node 246 - (1, HUFFMAN_EMIT_SYMBOL, 28), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (1, HUFFMAN_EMIT_SYMBOL, 29), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - (1, HUFFMAN_EMIT_SYMBOL, 30), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (1, HUFFMAN_EMIT_SYMBOL, 31), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - (1, HUFFMAN_EMIT_SYMBOL, 127), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (1, HUFFMAN_EMIT_SYMBOL, 220), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - (1, HUFFMAN_EMIT_SYMBOL, 249), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (254, 0, 0), - (255, 0, 0), - - # Node 247 - (2, HUFFMAN_EMIT_SYMBOL, 28), - (9, HUFFMAN_EMIT_SYMBOL, 28), - (23, HUFFMAN_EMIT_SYMBOL, 28), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (2, HUFFMAN_EMIT_SYMBOL, 29), - (9, HUFFMAN_EMIT_SYMBOL, 29), - (23, HUFFMAN_EMIT_SYMBOL, 29), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - (2, HUFFMAN_EMIT_SYMBOL, 30), - (9, HUFFMAN_EMIT_SYMBOL, 30), - (23, HUFFMAN_EMIT_SYMBOL, 30), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (2, HUFFMAN_EMIT_SYMBOL, 31), - (9, HUFFMAN_EMIT_SYMBOL, 31), - (23, HUFFMAN_EMIT_SYMBOL, 31), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - - # Node 248 - (3, HUFFMAN_EMIT_SYMBOL, 28), - (6, HUFFMAN_EMIT_SYMBOL, 28), - (10, HUFFMAN_EMIT_SYMBOL, 28), - (15, HUFFMAN_EMIT_SYMBOL, 28), - (24, HUFFMAN_EMIT_SYMBOL, 28), - (31, HUFFMAN_EMIT_SYMBOL, 28), - (41, HUFFMAN_EMIT_SYMBOL, 28), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (3, HUFFMAN_EMIT_SYMBOL, 29), - (6, HUFFMAN_EMIT_SYMBOL, 29), - (10, HUFFMAN_EMIT_SYMBOL, 29), - (15, HUFFMAN_EMIT_SYMBOL, 29), - (24, HUFFMAN_EMIT_SYMBOL, 29), - (31, HUFFMAN_EMIT_SYMBOL, 29), - (41, HUFFMAN_EMIT_SYMBOL, 29), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - - # Node 249 - (3, HUFFMAN_EMIT_SYMBOL, 30), - (6, HUFFMAN_EMIT_SYMBOL, 30), - (10, HUFFMAN_EMIT_SYMBOL, 30), - (15, HUFFMAN_EMIT_SYMBOL, 30), - (24, HUFFMAN_EMIT_SYMBOL, 30), - (31, HUFFMAN_EMIT_SYMBOL, 30), - (41, HUFFMAN_EMIT_SYMBOL, 30), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (3, HUFFMAN_EMIT_SYMBOL, 31), - (6, HUFFMAN_EMIT_SYMBOL, 31), - (10, HUFFMAN_EMIT_SYMBOL, 31), - (15, HUFFMAN_EMIT_SYMBOL, 31), - (24, HUFFMAN_EMIT_SYMBOL, 31), - (31, HUFFMAN_EMIT_SYMBOL, 31), - (41, HUFFMAN_EMIT_SYMBOL, 31), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - - # Node 250 - (2, HUFFMAN_EMIT_SYMBOL, 127), - (9, HUFFMAN_EMIT_SYMBOL, 127), - (23, HUFFMAN_EMIT_SYMBOL, 127), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (2, HUFFMAN_EMIT_SYMBOL, 220), - (9, HUFFMAN_EMIT_SYMBOL, 220), - (23, HUFFMAN_EMIT_SYMBOL, 220), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - (2, HUFFMAN_EMIT_SYMBOL, 249), - (9, HUFFMAN_EMIT_SYMBOL, 249), - (23, HUFFMAN_EMIT_SYMBOL, 249), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - - # Node 251 - (3, HUFFMAN_EMIT_SYMBOL, 127), - (6, HUFFMAN_EMIT_SYMBOL, 127), - (10, HUFFMAN_EMIT_SYMBOL, 127), - (15, HUFFMAN_EMIT_SYMBOL, 127), - (24, HUFFMAN_EMIT_SYMBOL, 127), - (31, HUFFMAN_EMIT_SYMBOL, 127), - (41, HUFFMAN_EMIT_SYMBOL, 127), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (3, HUFFMAN_EMIT_SYMBOL, 220), - (6, HUFFMAN_EMIT_SYMBOL, 220), - (10, HUFFMAN_EMIT_SYMBOL, 220), - (15, HUFFMAN_EMIT_SYMBOL, 220), - (24, HUFFMAN_EMIT_SYMBOL, 220), - (31, HUFFMAN_EMIT_SYMBOL, 220), - (41, HUFFMAN_EMIT_SYMBOL, 220), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - - # Node 252 - (3, HUFFMAN_EMIT_SYMBOL, 249), - (6, HUFFMAN_EMIT_SYMBOL, 249), - (10, HUFFMAN_EMIT_SYMBOL, 249), - (15, HUFFMAN_EMIT_SYMBOL, 249), - (24, HUFFMAN_EMIT_SYMBOL, 249), - (31, HUFFMAN_EMIT_SYMBOL, 249), - (41, HUFFMAN_EMIT_SYMBOL, 249), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (1, HUFFMAN_EMIT_SYMBOL, 10), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (1, HUFFMAN_EMIT_SYMBOL, 13), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - (1, HUFFMAN_EMIT_SYMBOL, 22), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - - # Node 253 - (2, HUFFMAN_EMIT_SYMBOL, 10), - (9, HUFFMAN_EMIT_SYMBOL, 10), - (23, HUFFMAN_EMIT_SYMBOL, 10), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (2, HUFFMAN_EMIT_SYMBOL, 13), - (9, HUFFMAN_EMIT_SYMBOL, 13), - (23, HUFFMAN_EMIT_SYMBOL, 13), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - (2, HUFFMAN_EMIT_SYMBOL, 22), - (9, HUFFMAN_EMIT_SYMBOL, 22), - (23, HUFFMAN_EMIT_SYMBOL, 22), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - - # Node 254 - (3, HUFFMAN_EMIT_SYMBOL, 10), - (6, HUFFMAN_EMIT_SYMBOL, 10), - (10, HUFFMAN_EMIT_SYMBOL, 10), - (15, HUFFMAN_EMIT_SYMBOL, 10), - (24, HUFFMAN_EMIT_SYMBOL, 10), - (31, HUFFMAN_EMIT_SYMBOL, 10), - (41, HUFFMAN_EMIT_SYMBOL, 10), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (3, HUFFMAN_EMIT_SYMBOL, 13), - (6, HUFFMAN_EMIT_SYMBOL, 13), - (10, HUFFMAN_EMIT_SYMBOL, 13), - (15, HUFFMAN_EMIT_SYMBOL, 13), - (24, HUFFMAN_EMIT_SYMBOL, 13), - (31, HUFFMAN_EMIT_SYMBOL, 13), - (41, HUFFMAN_EMIT_SYMBOL, 13), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - - # Node 255 - (3, HUFFMAN_EMIT_SYMBOL, 22), - (6, HUFFMAN_EMIT_SYMBOL, 22), - (10, HUFFMAN_EMIT_SYMBOL, 22), - (15, HUFFMAN_EMIT_SYMBOL, 22), - (24, HUFFMAN_EMIT_SYMBOL, 22), - (31, HUFFMAN_EMIT_SYMBOL, 22), - (41, HUFFMAN_EMIT_SYMBOL, 22), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), -] diff --git a/serverenv/lib/python3.9/site-packages/hpack/py.typed b/serverenv/lib/python3.9/site-packages/hpack/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/hpack/struct.py b/serverenv/lib/python3.9/site-packages/hpack/struct.py deleted file mode 100644 index 420c634..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/struct.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Contains structures for representing header fields with associated metadata. -""" -from __future__ import annotations - -from typing import TYPE_CHECKING, Any - -if TYPE_CHECKING: - from typing_extensions import Self, TypeAlias # pragma: no cover - - -class HeaderTuple(tuple[bytes, bytes]): - """ - A data structure that stores a single header field. - - HTTP headers can be thought of as tuples of ``(field name, field value)``. - A single header block is a sequence of such tuples. - - In HTTP/2, however, certain bits of additional information are required for - compressing these headers: in particular, whether the header field can be - safely added to the HPACK compression context. - - This class stores a header that can be added to the compression context. In - all other ways it behaves exactly like a tuple. - """ - - __slots__ = () - - indexable = True - - def __new__(cls, *args: Any) -> Self: - return tuple.__new__(cls, args) - - -class NeverIndexedHeaderTuple(HeaderTuple): - """ - A data structure that stores a single header field that cannot be added to - a HTTP/2 header compression context. - """ - - __slots__ = () - - indexable = False - - def __new__(cls, *args: Any) -> Self: - return tuple.__new__(cls, args) - - -Header: TypeAlias = "HeaderTuple | NeverIndexedHeaderTuple | tuple[bytes, bytes]" -HeaderWeaklyTyped: TypeAlias = "HeaderTuple | NeverIndexedHeaderTuple | tuple[bytes | str, bytes | str]" diff --git a/serverenv/lib/python3.9/site-packages/hpack/table.py b/serverenv/lib/python3.9/site-packages/hpack/table.py deleted file mode 100644 index 7b5338b..0000000 --- a/serverenv/lib/python3.9/site-packages/hpack/table.py +++ /dev/null @@ -1,237 +0,0 @@ -# flake8: noqa -from collections import deque -import logging -from typing import Optional - -from .exceptions import InvalidTableIndex - -log = logging.getLogger(__name__) - - -def table_entry_size(name: bytes, value: bytes) -> int: - """ - Calculates the size of a single entry - - This size is mostly irrelevant to us and defined - specifically to accommodate memory management for - lower level implementations. The 32 extra bytes are - considered the "maximum" overhead that would be - required to represent each entry in the table. - - See RFC7541 Section 4.1 - """ - return 32 + len(name) + len(value) - - -class HeaderTable: - """ - Implements the combined static and dynamic header table - - The name and value arguments for all the functions - should ONLY be byte strings (b'') however this is not - strictly enforced in the interface. - - See RFC7541 Section 2.3 - """ - #: Default maximum size of the dynamic table. See - #: RFC7540 Section 6.5.2. - DEFAULT_SIZE = 4096 - - #: Constant list of static headers. See RFC7541 Section - #: 2.3.1 and Appendix A - STATIC_TABLE = ( - (b':authority' , b'' ), # noqa - (b':method' , b'GET' ), # noqa - (b':method' , b'POST' ), # noqa - (b':path' , b'/' ), # noqa - (b':path' , b'/index.html' ), # noqa - (b':scheme' , b'http' ), # noqa - (b':scheme' , b'https' ), # noqa - (b':status' , b'200' ), # noqa - (b':status' , b'204' ), # noqa - (b':status' , b'206' ), # noqa - (b':status' , b'304' ), # noqa - (b':status' , b'400' ), # noqa - (b':status' , b'404' ), # noqa - (b':status' , b'500' ), # noqa - (b'accept-charset' , b'' ), # noqa - (b'accept-encoding' , b'gzip, deflate'), # noqa - (b'accept-language' , b'' ), # noqa - (b'accept-ranges' , b'' ), # noqa - (b'accept' , b'' ), # noqa - (b'access-control-allow-origin' , b'' ), # noqa - (b'age' , b'' ), # noqa - (b'allow' , b'' ), # noqa - (b'authorization' , b'' ), # noqa - (b'cache-control' , b'' ), # noqa - (b'content-disposition' , b'' ), # noqa - (b'content-encoding' , b'' ), # noqa - (b'content-language' , b'' ), # noqa - (b'content-length' , b'' ), # noqa - (b'content-location' , b'' ), # noqa - (b'content-range' , b'' ), # noqa - (b'content-type' , b'' ), # noqa - (b'cookie' , b'' ), # noqa - (b'date' , b'' ), # noqa - (b'etag' , b'' ), # noqa - (b'expect' , b'' ), # noqa - (b'expires' , b'' ), # noqa - (b'from' , b'' ), # noqa - (b'host' , b'' ), # noqa - (b'if-match' , b'' ), # noqa - (b'if-modified-since' , b'' ), # noqa - (b'if-none-match' , b'' ), # noqa - (b'if-range' , b'' ), # noqa - (b'if-unmodified-since' , b'' ), # noqa - (b'last-modified' , b'' ), # noqa - (b'link' , b'' ), # noqa - (b'location' , b'' ), # noqa - (b'max-forwards' , b'' ), # noqa - (b'proxy-authenticate' , b'' ), # noqa - (b'proxy-authorization' , b'' ), # noqa - (b'range' , b'' ), # noqa - (b'referer' , b'' ), # noqa - (b'refresh' , b'' ), # noqa - (b'retry-after' , b'' ), # noqa - (b'server' , b'' ), # noqa - (b'set-cookie' , b'' ), # noqa - (b'strict-transport-security' , b'' ), # noqa - (b'transfer-encoding' , b'' ), # noqa - (b'user-agent' , b'' ), # noqa - (b'vary' , b'' ), # noqa - (b'via' , b'' ), # noqa - (b'www-authenticate' , b'' ), # noqa - ) # noqa - - STATIC_TABLE_LENGTH = len(STATIC_TABLE) - - STATIC_TABLE_MAPPING: dict[bytes, tuple[int, dict[bytes, int]]] - - def __init__(self) -> None: - self._maxsize = HeaderTable.DEFAULT_SIZE - self._current_size = 0 - self.resized = False - self.dynamic_entries: deque[tuple[bytes, bytes]] = deque() - - def get_by_index(self, index: int) -> tuple[bytes, bytes]: - """ - Returns the entry specified by index - - Note that the table is 1-based ie an index of 0 is - invalid. This is due to the fact that a zero value - index signals that a completely unindexed header - follows. - - The entry will either be from the static table or - the dynamic table depending on the value of index. - """ - original_index = index - index -= 1 - if 0 <= index: - if index < HeaderTable.STATIC_TABLE_LENGTH: - return HeaderTable.STATIC_TABLE[index] - - index -= HeaderTable.STATIC_TABLE_LENGTH - if index < len(self.dynamic_entries): - return self.dynamic_entries[index] - - raise InvalidTableIndex("Invalid table index %d" % original_index) - - def __repr__(self) -> str: - return "HeaderTable(%d, %s, %r)" % ( - self._maxsize, - self.resized, - self.dynamic_entries - ) - - def add(self, name: bytes, value: bytes) -> None: - """ - Adds a new entry to the table - - We reduce the table size if the entry will make the - table size greater than maxsize. - """ - # We just clear the table if the entry is too big - size = table_entry_size(name, value) - if size > self._maxsize: - self.dynamic_entries.clear() - self._current_size = 0 - else: - # Add new entry - self.dynamic_entries.appendleft((name, value)) - self._current_size += size - self._shrink() - - def search(self, name: bytes, value: bytes) -> Optional[tuple[int, bytes, Optional[bytes]]]: - """ - Searches the table for the entry specified by name - and value - - Returns one of the following: - - ``None``, no match at all - - ``(index, name, None)`` for partial matches on name only. - - ``(index, name, value)`` for perfect matches. - """ - partial = None - - header_name_search_result = HeaderTable.STATIC_TABLE_MAPPING.get(name) - if header_name_search_result: - index = header_name_search_result[1].get(value) - if index is not None: - return index, name, value - else: - partial = (header_name_search_result[0], name, None) - - offset = HeaderTable.STATIC_TABLE_LENGTH + 1 - for (i, (n, v)) in enumerate(self.dynamic_entries): - if n == name: - if v == value: - return i + offset, n, v - elif partial is None: - partial = (i + offset, n, None) - return partial - - @property - def maxsize(self) -> int: - return self._maxsize - - @maxsize.setter - def maxsize(self, newmax: int) -> None: - newmax = int(newmax) - log.debug("Resizing header table to %d from %d", newmax, self._maxsize) - oldmax = self._maxsize - self._maxsize = newmax - self.resized = (newmax != oldmax) - if newmax <= 0: - self.dynamic_entries.clear() - self._current_size = 0 - elif oldmax > newmax: - self._shrink() - - def _shrink(self) -> None: - """ - Shrinks the dynamic table to be at or below maxsize - """ - cursize = self._current_size - while cursize > self._maxsize: - name, value = self.dynamic_entries.pop() - cursize -= table_entry_size(name, value) - log.debug("Evicting %s: %s from the header table", name, value) - self._current_size = cursize - - -def _build_static_table_mapping() -> dict[bytes, tuple[int, dict[bytes, int]]]: - """ - Build static table mapping from header name to tuple with next structure: - (, ). - - static_table_mapping used for hash searching. - """ - static_table_mapping: dict[bytes, tuple[int, dict[bytes, int]]] = {} - for index, (name, value) in enumerate(HeaderTable.STATIC_TABLE, 1): - header_name_search_result = static_table_mapping.setdefault(name, (index, {})) - header_name_search_result[1][value] = index - return static_table_mapping - - -HeaderTable.STATIC_TABLE_MAPPING = _build_static_table_mapping() diff --git a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/LICENSE b/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/LICENSE deleted file mode 100644 index 8a5dad9..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright P G Jones 2018. - -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/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/METADATA deleted file mode 100644 index c68e96e..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/METADATA +++ /dev/null @@ -1,159 +0,0 @@ -Metadata-Version: 2.1 -Name: Hypercorn -Version: 0.17.3 -Summary: A ASGI Server based on Hyper libraries and inspired by Gunicorn -Home-page: https://github.com/pgjones/hypercorn/ -License: MIT -Author: pgjones -Author-email: philip.graham.jones@googlemail.com -Requires-Python: >=3.8 -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Provides-Extra: docs -Provides-Extra: h3 -Provides-Extra: trio -Provides-Extra: uvloop -Requires-Dist: aioquic (>=0.9.0,<1.0) ; extra == "h3" -Requires-Dist: exceptiongroup (>=1.1.0) ; python_version < "3.11" -Requires-Dist: h11 -Requires-Dist: h2 (>=3.1.0) -Requires-Dist: priority -Requires-Dist: pydata_sphinx_theme ; extra == "docs" -Requires-Dist: sphinxcontrib_mermaid ; extra == "docs" -Requires-Dist: taskgroup ; python_version < "3.11" -Requires-Dist: tomli ; python_version < "3.11" -Requires-Dist: trio (>=0.22.0) ; extra == "trio" -Requires-Dist: typing_extensions ; python_version < "3.11" -Requires-Dist: uvloop (>=0.18) ; (platform_system != "Windows") and (extra == "uvloop") -Requires-Dist: wsproto (>=0.14.0) -Project-URL: Documentation, https://hypercorn.readthedocs.io -Project-URL: Repository, https://github.com/pgjones/hypercorn/ -Description-Content-Type: text/x-rst - -Hypercorn -========= - -.. image:: https://github.com/pgjones/hypercorn/raw/main/artwork/logo.png - :alt: Hypercorn logo - -|Build Status| |docs| |pypi| |http| |python| |license| - -Hypercorn is an `ASGI -`_ and -WSGI web server based on the sans-io hyper, `h11 -`_, `h2 -`_, and `wsproto -`_ libraries and inspired by -Gunicorn. Hypercorn supports HTTP/1, HTTP/2, WebSockets (over HTTP/1 -and HTTP/2), ASGI, and WSGI specifications. Hypercorn can utilise -asyncio, uvloop, or trio worker types. - -Hypercorn can optionally serve the current draft of the HTTP/3 -specification using the `aioquic -`_ library. To enable this install -the ``h3`` optional extra, ``pip install hypercorn[h3]`` and then -choose a quic binding e.g. ``hypercorn --quic-bind localhost:4433 -...``. - -Hypercorn was initially part of `Quart -`_ before being separated out into a -standalone server. Hypercorn forked from version 0.5.0 of Quart. - -Quickstart ----------- - -Hypercorn can be installed via `pip -`_, - -.. code-block:: console - - $ pip install hypercorn - -and requires Python 3.8 or higher. - -With hypercorn installed ASGI frameworks (or apps) can be served via -Hypercorn via the command line, - -.. code-block:: console - - $ hypercorn module:app - -Alternatively Hypercorn can be used programatically, - -.. code-block:: python - - import asyncio - from hypercorn.config import Config - from hypercorn.asyncio import serve - - from module import app - - asyncio.run(serve(app, Config())) - -learn more (including a Trio example of the above) in the `API usage -`_ -docs. - -Contributing ------------- - -Hypercorn is developed on `Github -`_. If you come across an issue, -or have a feature request please open an `issue -`_. If you want to -contribute a fix or the feature-implementation please do (typo fixes -welcome), by proposing a `pull request -`_. - -Testing -~~~~~~~ - -The best way to test Hypercorn is with `Tox -`_, - -.. code-block:: console - - $ pipenv install tox - $ tox - -this will check the code style and run the tests. - -Help ----- - -The Hypercorn `documentation `_ is -the best place to start, after that try searching stack overflow, if -you still can't find an answer please `open an issue -`_. - - -.. |Build Status| image:: https://github.com/pgjones/hypercorn/actions/workflows/ci.yml/badge.svg - :target: https://github.com/pgjones/hypercorn/commits/main - -.. |docs| image:: https://img.shields.io/badge/docs-passing-brightgreen.svg - :target: https://hypercorn.readthedocs.io - -.. |pypi| image:: https://img.shields.io/pypi/v/hypercorn.svg - :target: https://pypi.python.org/pypi/Hypercorn/ - -.. |http| image:: https://img.shields.io/badge/http-1.0,1.1,2-orange.svg - :target: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol - -.. |python| image:: https://img.shields.io/pypi/pyversions/hypercorn.svg - :target: https://pypi.python.org/pypi/Hypercorn/ - -.. |license| image:: https://img.shields.io/badge/license-MIT-blue.svg - :target: https://github.com/pgjones/hypercorn/blob/main/LICENSE - diff --git a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/RECORD deleted file mode 100644 index bf4db9e..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/RECORD +++ /dev/null @@ -1,86 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/__main__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/app_wrappers.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/lifespan.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/run.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/statsd.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/task_group.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/tcp_server.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/udp_server.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/worker_context.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/config.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/events.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/logging.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/middleware/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/middleware/dispatcher.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/middleware/http_to_https.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/middleware/proxy_fix.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/middleware/wsgi.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/events.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h11.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h2.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h3.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/http_stream.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/quic.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/protocol/ws_stream.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/run.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/statsd.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/lifespan.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/run.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/statsd.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/task_group.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/tcp_server.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/udp_server.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/trio/worker_context.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/typing.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hypercorn/utils.cpython-39.pyc,, -../../../bin/hypercorn,sha256=wqJxEbtKduOjkorQ9ChPW-c_ZPBOY9lIh0hi7i27NGs,252 -hypercorn-0.17.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -hypercorn-0.17.3.dist-info/LICENSE,sha256=HjGdhzPYNEZ3zQ7mwqjMBgHHRId5HViyayt-8GMMK38,1050 -hypercorn-0.17.3.dist-info/METADATA,sha256=-eP10Zqdx9xDecBmEfaSNGenCmusyLDbzEu3pkjMkI0,5434 -hypercorn-0.17.3.dist-info/RECORD,, -hypercorn-0.17.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88 -hypercorn-0.17.3.dist-info/entry_points.txt,sha256=jvhlIIEg7Z6C2_i4XPhBYy7N4uV1X-mcq_aL7IdowHg,53 -hypercorn/__init__.py,sha256=JlzzQ7LnV2v7T6S-CpHnpO9rjGzlh-tTdvCGg5V_Qjk,86 -hypercorn/__main__.py,sha256=OIyNIXGdEUe2LJhK4rKPFOTCngaUgbYKMqD_rMsamao,10972 -hypercorn/app_wrappers.py,sha256=PsLFWQNtFDThW_SWBvzFqcgbqdDDpYbdD27bQkBUJ00,5389 -hypercorn/asyncio/__init__.py,sha256=ddIYv0p72T8Ra_NV5q4iZ0hHd4fr4hWjVi7XPOLpZ00,1444 -hypercorn/asyncio/lifespan.py,sha256=OhLgedL5Bn1p5Qmjvd7gHHSrE782AUKDnxBkkBqNf7U,4442 -hypercorn/asyncio/run.py,sha256=DJw4qnY2JrSai8Q8UWPWI7p4alnq8yxAlWRRQMpUHFc,8125 -hypercorn/asyncio/statsd.py,sha256=RHXwkQSEhCZtEi4XJ0SumGstT8mFDDq61Y4xOV4C2sw,769 -hypercorn/asyncio/task_group.py,sha256=Lf2iTNqU0tBgyXIbc30fIK3sspYxvLgbBxsNnJNRd0E,2231 -hypercorn/asyncio/tcp_server.py,sha256=6EqBg8DNkYqNSKHyZPLh8qmKbo2Z1lCErspfOLik0Wg,4598 -hypercorn/asyncio/udp_server.py,sha256=FaxqynS4LErpgHqUZEO5blYMR6t6N5TQanmdeCsOUx0,2401 -hypercorn/asyncio/worker_context.py,sha256=L3w28-QbXY9QuzvHn6EnZe_fBqbvv_HmtLqGj-RFrSY,2134 -hypercorn/config.py,sha256=Pnpym031mFBltRY33aP58X3RvPrhftFEihBYEaLekWs,13538 -hypercorn/events.py,sha256=tmNw0orBDPMuEVvBx98JuSv72yiHllHr55z26V4zPS0,383 -hypercorn/logging.py,sha256=ZBrjXxr2LDTSJ9U2LHTA5_IVOUuApa_FgikyORUoDP4,7385 -hypercorn/middleware/__init__.py,sha256=bamUu2p0U30kAk_x2ZOWgFIcFh72Tl4MjllMt1yn-Ok,401 -hypercorn/middleware/dispatcher.py,sha256=I20_vSlw5NjIOFftenpnAVErXZkUnpATankQHarXcnc,4306 -hypercorn/middleware/http_to_https.py,sha256=SWtIjaRPGgSXt2TA2_xzvgUbtB1DOPtQkoaqqauJlME,2619 -hypercorn/middleware/proxy_fix.py,sha256=nZyfddYBHzyvXECJlwxOmKSSlyl0_Yv4vxpcBBJxK1o,2693 -hypercorn/middleware/wsgi.py,sha256=Ohb7QrNsNshw6TQNBRTqki1Hn4R_D8H8ditRLW8qy8E,1489 -hypercorn/protocol/__init__.py,sha256=yoTaVUL8hR-qX4CKNRy_MxTCJH7J15RmqQZbAPf9Yu4,2996 -hypercorn/protocol/events.py,sha256=FjEbAIfmV-qRhwvqtrsbYq6PY_rVm6G8lyF53yiCXRU,1174 -hypercorn/protocol/h11.py,sha256=jqDniagYmzxs4ITK7Vd8j4eIERuOrN-oYXpVJV34ocI,11911 -hypercorn/protocol/h2.py,sha256=Ik-XdfqUNwvJebAm22PeVIub7IRcvI31ykXiKmrQ9Nw,15543 -hypercorn/protocol/h3.py,sha256=x_M7eCZ_kJCWDApUbY4t_Li4lqAhrzTDTjKXq6-ivp4,5627 -hypercorn/protocol/http_stream.py,sha256=wUB-c1ClRYITRck-2H-VWNosdKMbuT_7OqqbvCj6Vlg,9996 -hypercorn/protocol/quic.py,sha256=7sTSR0JwRg5y6Cvh1sbLlLv3msO6oG90guB3Y_vdVfE,5789 -hypercorn/protocol/ws_stream.py,sha256=6KvW8P6Mel-JLLLK-JN0Yw_o-fTg1OxBjpi1klnMssI,15198 -hypercorn/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 -hypercorn/run.py,sha256=Qwn9hdNJVMpIH3Ciz7cwvtUGO4p-B3OUphLRKwmEOSY,4731 -hypercorn/statsd.py,sha256=zAvhHTc_YJL01Em1HBM6Cv8N2WJtrkx4W_M52YDvbIc,3889 -hypercorn/trio/__init__.py,sha256=rnH1OFZwswI8h9c1jysoCC8FOeBYLAWCxH4bqC-bdYM,1559 -hypercorn/trio/lifespan.py,sha256=h8XFl7dY8TlZe8PtelbvjWAsFgrA1na6MtZeQI1nSrI,4020 -hypercorn/trio/run.py,sha256=AJbMkOn7HN1HxW3o2ei1FrBBbGazh_TVVYwxLtlYfpQ,5364 -hypercorn/trio/statsd.py,sha256=GNjvE-sIyR2dxt3XKUq0sD2ruRTsz8Mz7QKDMSHd1LI,493 -hypercorn/trio/task_group.py,sha256=L85BAJi77V-LJKi7lPRNmfZBeJrOj1rLlRxCSL83FGQ,2425 -hypercorn/trio/tcp_server.py,sha256=SDrcBYLNe-gajWw-gqcTRmtC0kIZIlAFeR_7U8lMMPE,4672 -hypercorn/trio/udp_server.py,sha256=nlbb36cRQerSEG3rtKJdL5_jay1Q2jp7-KjzGvuJvA8,1736 -hypercorn/trio/worker_context.py,sha256=ywhzrdK4bmckMQpI0ZDvvzkbY3cUQHj_Wd03gY6mfuk,2282 -hypercorn/typing.py,sha256=aypVV_aHw31tm1c757N8Px7cHosFKMGwDMBc3iE91UM,8014 -hypercorn/utils.py,sha256=olYC7o10l79CK-d8wD-LxQHJoLq1YPeTXUPmePVFwCM,6506 diff --git a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/WHEEL deleted file mode 100644 index d73ccaa..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: poetry-core 1.9.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/entry_points.txt b/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/entry_points.txt deleted file mode 100644 index e941001..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn-0.17.3.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -hypercorn=hypercorn.__main__:main - diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/__init__.py b/serverenv/lib/python3.9/site-packages/hypercorn/__init__.py deleted file mode 100644 index 5931e8c..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import annotations - -from .config import Config - -__all__ = ("Config",) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/__main__.py b/serverenv/lib/python3.9/site-packages/hypercorn/__main__.py deleted file mode 100644 index aed33b1..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/__main__.py +++ /dev/null @@ -1,308 +0,0 @@ -from __future__ import annotations - -import argparse -import ssl -import sys -import warnings -from typing import List, Optional - -from .config import Config -from .run import run - -sentinel = object() - - -def _load_config(config_path: Optional[str]) -> Config: - if config_path is None: - return Config() - elif config_path.startswith("python:"): - return Config.from_object(config_path[len("python:") :]) - elif config_path.startswith("file:"): - return Config.from_pyfile(config_path[len("file:") :]) - else: - return Config.from_toml(config_path) - - -def main(sys_args: Optional[List[str]] = None) -> int: - parser = argparse.ArgumentParser() - parser.add_argument( - "application", help="The application to dispatch to as path.to.module:instance.path" - ) - parser.add_argument("--access-log", help="Deprecated, see access-logfile", default=sentinel) - parser.add_argument( - "--access-logfile", - help="The target location for the access log, use `-` for stdout", - default=sentinel, - ) - parser.add_argument( - "--access-logformat", - help="The log format for the access log, see help docs", - default=sentinel, - ) - parser.add_argument( - "--backlog", help="The maximum number of pending connections", type=int, default=sentinel - ) - parser.add_argument( - "-b", - "--bind", - dest="binds", - help=""" The TCP host/address to bind to. Should be either host:port, host, - unix:path or fd://num, e.g. 127.0.0.1:5000, 127.0.0.1, - unix:/tmp/socket or fd://33 respectively. """, - default=[], - action="append", - ) - parser.add_argument("--ca-certs", help="Path to the SSL CA certificate file", default=sentinel) - parser.add_argument("--certfile", help="Path to the SSL certificate file", default=sentinel) - parser.add_argument("--cert-reqs", help="See verify mode argument", type=int, default=sentinel) - parser.add_argument("--ciphers", help="Ciphers to use for the SSL setup", default=sentinel) - parser.add_argument( - "-c", - "--config", - help="Location of a TOML config file, or when prefixed with `file:` a Python file, or when prefixed with `python:` a Python module.", # noqa: E501 - default=None, - ) - parser.add_argument( - "--debug", - help="Enable debug mode, i.e. extra logging and checks", - action="store_true", - default=sentinel, - ) - parser.add_argument("--error-log", help="Deprecated, see error-logfile", default=sentinel) - parser.add_argument( - "--error-logfile", - "--log-file", - dest="error_logfile", - help="The target location for the error log, use `-` for stderr", - default=sentinel, - ) - parser.add_argument( - "--graceful-timeout", - help="""Time to wait after SIGTERM or Ctrl-C for any remaining requests (tasks) - to complete.""", - default=sentinel, - type=int, - ) - parser.add_argument( - "--read-timeout", - help="""Seconds to wait before timing out reads on TCP sockets""", - default=sentinel, - type=int, - ) - parser.add_argument( - "--max-requests", - help="""Maximum number of requests a worker will process before restarting""", - default=sentinel, - type=int, - ) - parser.add_argument( - "--max-requests-jitter", - help="This jitter causes the max-requests per worker to be " - "randomized by randint(0, max_requests_jitter)", - default=sentinel, - type=int, - ) - parser.add_argument( - "-g", "--group", help="Group to own any unix sockets.", default=sentinel, type=int - ) - parser.add_argument( - "-k", - "--worker-class", - dest="worker_class", - help="The type of worker to use. " - "Options include asyncio, uvloop (pip install hypercorn[uvloop]), " - "and trio (pip install hypercorn[trio]).", - default=sentinel, - ) - parser.add_argument( - "--keep-alive", - help="Seconds to keep inactive connections alive for", - default=sentinel, - type=int, - ) - parser.add_argument("--keyfile", help="Path to the SSL key file", default=sentinel) - parser.add_argument( - "--keyfile-password", help="Password to decrypt the SSL key file", default=sentinel - ) - parser.add_argument( - "--insecure-bind", - dest="insecure_binds", - help="""The TCP host/address to bind to. SSL options will not apply to these binds. - See *bind* for formatting options. Care must be taken! See HTTP -> HTTPS redirection docs. - """, - default=[], - action="append", - ) - parser.add_argument( - "--log-config", - help=""""A Python logging configuration file. This can be prefixed with - 'json:' or 'toml:' to load the configuration from a file in - that format. Default is the logging ini format.""", - default=sentinel, - ) - parser.add_argument( - "--log-level", help="The (error) log level, defaults to info", default=sentinel - ) - parser.add_argument( - "-p", "--pid", help="Location to write the PID (Program ID) to.", default=sentinel - ) - parser.add_argument( - "--quic-bind", - dest="quic_binds", - help="""The UDP/QUIC host/address to bind to. See *bind* for formatting - options. - """, - default=[], - action="append", - ) - parser.add_argument( - "--reload", - help="Enable automatic reloads on code changes", - action="store_true", - default=sentinel, - ) - parser.add_argument( - "--root-path", help="The setting for the ASGI root_path variable", default=sentinel - ) - parser.add_argument( - "--server-name", - dest="server_names", - help="""The hostnames that can be served, requests to different hosts - will be responded to with 404s. - """, - default=[], - action="append", - ) - parser.add_argument( - "--statsd-host", help="The host:port of the statsd server", default=sentinel - ) - parser.add_argument("--statsd-prefix", help="Prefix for all statsd messages", default="") - parser.add_argument( - "-m", - "--umask", - help="The permissions bit mask to use on any unix sockets.", - default=sentinel, - type=int, - ) - parser.add_argument( - "-u", "--user", help="User to own any unix sockets.", default=sentinel, type=int - ) - - def _convert_verify_mode(value: str) -> ssl.VerifyMode: - try: - return ssl.VerifyMode[value] - except KeyError: - raise argparse.ArgumentTypeError(f"'{value}' is not a valid verify mode") - - parser.add_argument( - "--verify-mode", - help="SSL verify mode for peer's certificate, see ssl.VerifyMode enum for possible values.", - type=_convert_verify_mode, - default=sentinel, - ) - parser.add_argument( - "--websocket-ping-interval", - help="""If set this is the time in seconds between pings sent to the client. - This can be used to keep the websocket connection alive.""", - default=sentinel, - type=int, - ) - parser.add_argument( - "-w", - "--workers", - dest="workers", - help="The number of workers to spawn and use", - default=sentinel, - type=int, - ) - args = parser.parse_args(sys_args or sys.argv[1:]) - config = _load_config(args.config) - config.application_path = args.application - - if args.log_level is not sentinel: - config.loglevel = args.log_level - if args.access_logformat is not sentinel: - config.access_log_format = args.access_logformat - if args.access_log is not sentinel: - warnings.warn( - "The --access-log argument is deprecated, use `--access-logfile` instead", - DeprecationWarning, - ) - config.accesslog = args.access_log - if args.access_logfile is not sentinel: - config.accesslog = args.access_logfile - if args.backlog is not sentinel: - config.backlog = args.backlog - if args.ca_certs is not sentinel: - config.ca_certs = args.ca_certs - if args.certfile is not sentinel: - config.certfile = args.certfile - if args.cert_reqs is not sentinel: - config.cert_reqs = args.cert_reqs - if args.ciphers is not sentinel: - config.ciphers = args.ciphers - if args.debug is not sentinel: - config.debug = args.debug - if args.error_log is not sentinel: - warnings.warn( - "The --error-log argument is deprecated, use `--error-logfile` instead", - DeprecationWarning, - ) - config.errorlog = args.error_log - if args.error_logfile is not sentinel: - config.errorlog = args.error_logfile - if args.graceful_timeout is not sentinel: - config.graceful_timeout = args.graceful_timeout - if args.read_timeout is not sentinel: - config.read_timeout = args.read_timeout - if args.group is not sentinel: - config.group = args.group - if args.keep_alive is not sentinel: - config.keep_alive_timeout = args.keep_alive - if args.keyfile is not sentinel: - config.keyfile = args.keyfile - if args.keyfile_password is not sentinel: - config.keyfile_password = args.keyfile_password - if args.log_config is not sentinel: - config.logconfig = args.log_config - if args.max_requests is not sentinel: - config.max_requests = args.max_requests - if args.max_requests_jitter is not sentinel: - config.max_requests_jitter = args.max_requests - if args.pid is not sentinel: - config.pid_path = args.pid - if args.root_path is not sentinel: - config.root_path = args.root_path - if args.reload is not sentinel: - config.use_reloader = args.reload - if args.statsd_host is not sentinel: - config.statsd_host = args.statsd_host - if args.statsd_prefix is not sentinel: - config.statsd_prefix = args.statsd_prefix - if args.umask is not sentinel: - config.umask = args.umask - if args.user is not sentinel: - config.user = args.user - if args.worker_class is not sentinel: - config.worker_class = args.worker_class - if args.verify_mode is not sentinel: - config.verify_mode = args.verify_mode - if args.websocket_ping_interval is not sentinel: - config.websocket_ping_interval = args.websocket_ping_interval - if args.workers is not sentinel: - config.workers = args.workers - - if len(args.binds) > 0: - config.bind = args.binds - if len(args.insecure_binds) > 0: - config.insecure_bind = args.insecure_binds - if len(args.quic_binds) > 0: - config.quic_bind = args.quic_binds - if len(args.server_names) > 0: - config.server_names = args.server_names - - return run(config) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/app_wrappers.py b/serverenv/lib/python3.9/site-packages/hypercorn/app_wrappers.py deleted file mode 100644 index 56c1bfa..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/app_wrappers.py +++ /dev/null @@ -1,163 +0,0 @@ -from __future__ import annotations - -import sys -from functools import partial -from io import BytesIO -from typing import Callable, List, Optional, Tuple - -from .typing import ( - ASGIFramework, - ASGIReceiveCallable, - ASGISendCallable, - HTTPScope, - Scope, - WSGIFramework, -) - - -class InvalidPathError(Exception): - pass - - -class ASGIWrapper: - def __init__(self, app: ASGIFramework) -> None: - self.app = app - - async def __call__( - self, - scope: Scope, - receive: ASGIReceiveCallable, - send: ASGISendCallable, - sync_spawn: Callable, - call_soon: Callable, - ) -> None: - await self.app(scope, receive, send) - - -class WSGIWrapper: - def __init__(self, app: WSGIFramework, max_body_size: int) -> None: - self.app = app - self.max_body_size = max_body_size - - async def __call__( - self, - scope: Scope, - receive: ASGIReceiveCallable, - send: ASGISendCallable, - sync_spawn: Callable, - call_soon: Callable, - ) -> None: - if scope["type"] == "http": - await self.handle_http(scope, receive, send, sync_spawn, call_soon) - elif scope["type"] == "websocket": - await send({"type": "websocket.close"}) # type: ignore - elif scope["type"] == "lifespan": - return - else: - raise Exception(f"Unknown scope type, {scope['type']}") - - async def handle_http( - self, - scope: HTTPScope, - receive: ASGIReceiveCallable, - send: ASGISendCallable, - sync_spawn: Callable, - call_soon: Callable, - ) -> None: - body = bytearray() - while True: - message = await receive() - body.extend(message.get("body", b"")) # type: ignore - if len(body) > self.max_body_size: - await send({"type": "http.response.start", "status": 400, "headers": []}) - await send({"type": "http.response.body", "body": b"", "more_body": False}) - return - if not message.get("more_body"): - break - - try: - environ = _build_environ(scope, body) - except InvalidPathError: - await send({"type": "http.response.start", "status": 404, "headers": []}) - else: - await sync_spawn(self.run_app, environ, partial(call_soon, send)) - await send({"type": "http.response.body", "body": b"", "more_body": False}) - - def run_app(self, environ: dict, send: Callable) -> None: - headers: List[Tuple[bytes, bytes]] - response_started = False - status_code: Optional[int] = None - - def start_response( - status: str, - response_headers: List[Tuple[str, str]], - exc_info: Optional[Exception] = None, - ) -> None: - nonlocal headers, response_started, status_code - - raw, _ = status.split(" ", 1) - status_code = int(raw) - headers = [ - (name.lower().encode("latin-1"), value.encode("latin-1")) - for name, value in response_headers - ] - response_started = True - - response_body = self.app(environ, start_response) - - if not response_started: - raise RuntimeError("WSGI app did not call start_response") - - send({"type": "http.response.start", "status": status_code, "headers": headers}) - try: - for output in response_body: - send({"type": "http.response.body", "body": output, "more_body": True}) - finally: - if hasattr(response_body, "close"): - response_body.close() - - -def _build_environ(scope: HTTPScope, body: bytes) -> dict: - server = scope.get("server") or ("localhost", 80) - path = scope["path"] - script_name = scope.get("root_path", "") - if path.startswith(script_name): - path = path[len(script_name) :] - path = path if path != "" else "/" - else: - raise InvalidPathError() - - environ = { - "REQUEST_METHOD": scope["method"], - "SCRIPT_NAME": script_name.encode("utf8").decode("latin1"), - "PATH_INFO": path.encode("utf8").decode("latin1"), - "QUERY_STRING": scope["query_string"].decode("ascii"), - "SERVER_NAME": server[0], - "SERVER_PORT": server[1], - "SERVER_PROTOCOL": "HTTP/%s" % scope["http_version"], - "wsgi.version": (1, 0), - "wsgi.url_scheme": scope.get("scheme", "http"), - "wsgi.input": BytesIO(body), - "wsgi.errors": sys.stdout, - "wsgi.multithread": True, - "wsgi.multiprocess": True, - "wsgi.run_once": False, - } - - if scope.get("client") is not None: - environ["REMOTE_ADDR"] = scope["client"][0] - - for raw_name, raw_value in scope.get("headers", []): - name = raw_name.decode("latin1") - if name == "content-length": - corrected_name = "CONTENT_LENGTH" - elif name == "content-type": - corrected_name = "CONTENT_TYPE" - else: - corrected_name = "HTTP_%s" % name.upper().replace("-", "_") - # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in case - value = raw_value.decode("latin1") - if corrected_name in environ: - value = environ[corrected_name] + "," + value # type: ignore - environ[corrected_name] = value - return environ diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/__init__.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/__init__.py deleted file mode 100644 index 3755da0..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -from __future__ import annotations - -import warnings -from typing import Awaitable, Callable, Literal, Optional - -from .run import worker_serve -from ..config import Config -from ..typing import Framework -from ..utils import wrap_app - - -async def serve( - app: Framework, - config: Config, - *, - shutdown_trigger: Optional[Callable[..., Awaitable]] = None, - mode: Optional[Literal["asgi", "wsgi"]] = None, -) -> None: - """Serve an ASGI or WSGI framework app given the config. - - This allows for a programmatic way to serve an ASGI or WSGI - framework, it can be used via, - - .. code-block:: python - - asyncio.run(serve(app, config)) - - It is assumed that the event-loop is configured before calling - this function, therefore configuration values that relate to loop - setup or process setup are ignored. - - Arguments: - app: The ASGI or WSGI application to serve. - config: A Hypercorn configuration object. - shutdown_trigger: This should return to trigger a graceful - shutdown. - mode: Specify if the app is WSGI or ASGI. - """ - if config.debug: - warnings.warn("The config `debug` has no affect when using serve", Warning) - if config.workers != 1: - warnings.warn("The config `workers` has no affect when using serve", Warning) - - await worker_serve( - wrap_app(app, config.wsgi_max_body_size, mode), config, shutdown_trigger=shutdown_trigger - ) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/lifespan.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/lifespan.py deleted file mode 100644 index bd22c8f..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/lifespan.py +++ /dev/null @@ -1,124 +0,0 @@ -from __future__ import annotations - -import asyncio -import sys -from functools import partial -from typing import Any, Callable - -from ..config import Config -from ..typing import AppWrapper, ASGIReceiveEvent, ASGISendEvent, LifespanScope, LifespanState -from ..utils import LifespanFailureError, LifespanTimeoutError - -if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - - -class UnexpectedMessageError(Exception): - pass - - -class Lifespan: - def __init__( - self, - app: AppWrapper, - config: Config, - loop: asyncio.AbstractEventLoop, - lifespan_state: LifespanState, - ) -> None: - self.app = app - self.config = config - self.startup = asyncio.Event() - self.shutdown = asyncio.Event() - self.app_queue: asyncio.Queue = asyncio.Queue(config.max_app_queue_size) - self.supported = True - self.loop = loop - self.state = lifespan_state - - # This mimics the Trio nursery.start task_status and is - # required to ensure the support has been checked before - # waiting on timeouts. - self._started = asyncio.Event() - - async def handle_lifespan(self) -> None: - self._started.set() - scope: LifespanScope = { - "type": "lifespan", - "asgi": {"spec_version": "2.0", "version": "3.0"}, - "state": self.state, - } - - def _call_soon(func: Callable, *args: Any) -> Any: - future = asyncio.run_coroutine_threadsafe(func(*args), self.loop) - return future.result() - - try: - await self.app( - scope, - self.asgi_receive, - self.asgi_send, - partial(self.loop.run_in_executor, None), - _call_soon, - ) - except LifespanFailureError: - # Lifespan failures should crash the server - raise - except (BaseExceptionGroup, Exception) as error: - if isinstance(error, BaseExceptionGroup): - failure_error = error.subgroup(LifespanFailureError) - if failure_error is not None: - # Lifespan failures should crash the server - raise failure_error - - self.supported = False - if not self.startup.is_set(): - await self.config.log.warning( - "ASGI Framework Lifespan error, continuing without Lifespan support" - ) - elif not self.shutdown.is_set(): - await self.config.log.exception( - "ASGI Framework Lifespan error, shutdown without Lifespan support" - ) - else: - await self.config.log.exception("ASGI Framework Lifespan errored after shutdown.") - finally: - self.startup.set() - self.shutdown.set() - - async def wait_for_startup(self) -> None: - await self._started.wait() - if not self.supported: - return - - await self.app_queue.put({"type": "lifespan.startup"}) - try: - await asyncio.wait_for(self.startup.wait(), timeout=self.config.startup_timeout) - except asyncio.TimeoutError as error: - raise LifespanTimeoutError("startup") from error - - async def wait_for_shutdown(self) -> None: - await self._started.wait() - if not self.supported: - return - - await self.app_queue.put({"type": "lifespan.shutdown"}) - try: - await asyncio.wait_for(self.shutdown.wait(), timeout=self.config.shutdown_timeout) - except asyncio.TimeoutError as error: - raise LifespanTimeoutError("shutdown") from error - - async def asgi_receive(self) -> ASGIReceiveEvent: - return await self.app_queue.get() - - async def asgi_send(self, message: ASGISendEvent) -> None: - if message["type"] == "lifespan.startup.complete": - self.startup.set() - elif message["type"] == "lifespan.shutdown.complete": - self.shutdown.set() - elif message["type"] == "lifespan.startup.failed": - self.startup.set() - raise LifespanFailureError("startup", message.get("message", "")) - elif message["type"] == "lifespan.shutdown.failed": - self.shutdown.set() - raise LifespanFailureError("shutdown", message.get("message", "")) - else: - raise UnexpectedMessageError(message["type"]) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/run.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/run.py deleted file mode 100644 index 93bd7fc..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/run.py +++ /dev/null @@ -1,242 +0,0 @@ -from __future__ import annotations - -import asyncio -import platform -import signal -import ssl -import sys -from functools import partial -from multiprocessing.synchronize import Event as EventType -from os import getpid -from random import randint -from socket import socket -from typing import Any, Awaitable, Callable, Optional, Set - -from .lifespan import Lifespan -from .statsd import StatsdLogger -from .tcp_server import TCPServer -from .udp_server import UDPServer -from .worker_context import WorkerContext -from ..config import Config, Sockets -from ..typing import AppWrapper, LifespanState -from ..utils import ( - check_multiprocess_shutdown_event, - load_application, - raise_shutdown, - repr_socket_addr, - ShutdownError, -) - -try: - from asyncio import Runner -except ImportError: - from taskgroup import Runner # type: ignore - -try: - from asyncio import TaskGroup -except ImportError: - from taskgroup import TaskGroup # type: ignore - -if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - - -def _share_socket(sock: socket) -> socket: - # Windows requires the socket be explicitly shared across - # multiple workers (processes). - from socket import fromshare # type: ignore - - sock_data = sock.share(getpid()) # type: ignore - return fromshare(sock_data) - - -async def worker_serve( - app: AppWrapper, - config: Config, - *, - sockets: Optional[Sockets] = None, - shutdown_trigger: Optional[Callable[..., Awaitable]] = None, -) -> None: - config.set_statsd_logger_class(StatsdLogger) - - loop = asyncio.get_event_loop() - - if shutdown_trigger is None: - signal_event = asyncio.Event() - - def _signal_handler(*_: Any) -> None: # noqa: N803 - signal_event.set() - - for signal_name in {"SIGINT", "SIGTERM", "SIGBREAK"}: - if hasattr(signal, signal_name): - try: - loop.add_signal_handler(getattr(signal, signal_name), _signal_handler) - except NotImplementedError: - # Add signal handler may not be implemented on Windows - signal.signal(getattr(signal, signal_name), _signal_handler) - - shutdown_trigger = signal_event.wait - - lifespan_state: LifespanState = {} - lifespan = Lifespan(app, config, loop, lifespan_state) - - lifespan_task = loop.create_task(lifespan.handle_lifespan()) - await lifespan.wait_for_startup() - if lifespan_task.done(): - exception = lifespan_task.exception() - if exception is not None: - raise exception - - if sockets is None: - sockets = config.create_sockets() - - ssl_handshake_timeout = None - if config.ssl_enabled: - ssl_context = config.create_ssl_context() - ssl_handshake_timeout = config.ssl_handshake_timeout - - max_requests = None - if config.max_requests is not None: - max_requests = config.max_requests + randint(0, config.max_requests_jitter) - context = WorkerContext(max_requests) - server_tasks: Set[asyncio.Task] = set() - - async def _server_callback(reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None: - nonlocal server_tasks - - task = asyncio.current_task(loop) - server_tasks.add(task) - task.add_done_callback(server_tasks.discard) - await TCPServer(app, loop, config, context, lifespan_state, reader, writer) - - servers = [] - for sock in sockets.secure_sockets: - if config.workers > 1 and platform.system() == "Windows": - sock = _share_socket(sock) - - servers.append( - await asyncio.start_server( - _server_callback, - backlog=config.backlog, - ssl=ssl_context, - sock=sock, - ssl_handshake_timeout=ssl_handshake_timeout, - ) - ) - bind = repr_socket_addr(sock.family, sock.getsockname()) - await config.log.info(f"Running on https://{bind} (CTRL + C to quit)") - - for sock in sockets.insecure_sockets: - if config.workers > 1 and platform.system() == "Windows": - sock = _share_socket(sock) - - servers.append( - await asyncio.start_server(_server_callback, backlog=config.backlog, sock=sock) - ) - bind = repr_socket_addr(sock.family, sock.getsockname()) - await config.log.info(f"Running on http://{bind} (CTRL + C to quit)") - - for sock in sockets.quic_sockets: - if config.workers > 1 and platform.system() == "Windows": - sock = _share_socket(sock) - - _, protocol = await loop.create_datagram_endpoint( - lambda: UDPServer(app, loop, config, context, lifespan_state), sock=sock - ) - task = loop.create_task(protocol.run()) - server_tasks.add(task) - task.add_done_callback(server_tasks.discard) - bind = repr_socket_addr(sock.family, sock.getsockname()) - await config.log.info(f"Running on https://{bind} (QUIC) (CTRL + C to quit)") - - try: - async with TaskGroup() as task_group: - task_group.create_task(raise_shutdown(shutdown_trigger)) - task_group.create_task(raise_shutdown(context.terminate.wait)) - except BaseExceptionGroup as error: - _, other_errors = error.split((ShutdownError, KeyboardInterrupt)) - if other_errors is not None: - raise other_errors - except (ShutdownError, KeyboardInterrupt): - pass - finally: - await context.terminated.set() - - for server in servers: - server.close() - await server.wait_closed() - - try: - gathered_server_tasks = asyncio.gather(*server_tasks) - await asyncio.wait_for(gathered_server_tasks, config.graceful_timeout) - except asyncio.TimeoutError: - pass - finally: - # Retrieve the Gathered Tasks Cancelled Exception, to - # prevent a warning that this hasn't been done. - gathered_server_tasks.exception() - - await lifespan.wait_for_shutdown() - lifespan_task.cancel() - await lifespan_task - - -def asyncio_worker( - config: Config, sockets: Optional[Sockets] = None, shutdown_event: Optional[EventType] = None -) -> None: - app = load_application(config.application_path, config.wsgi_max_body_size) - - shutdown_trigger = None - if shutdown_event is not None: - shutdown_trigger = partial(check_multiprocess_shutdown_event, shutdown_event, asyncio.sleep) - - if config.workers > 1 and platform.system() == "Windows": - asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # type: ignore - - _run( - partial(worker_serve, app, config, sockets=sockets), - debug=config.debug, - shutdown_trigger=shutdown_trigger, - ) - - -def uvloop_worker( - config: Config, sockets: Optional[Sockets] = None, shutdown_event: Optional[EventType] = None -) -> None: - try: - import uvloop - except ImportError as error: - raise Exception("uvloop is not installed") from error - - app = load_application(config.application_path, config.wsgi_max_body_size) - - shutdown_trigger = None - if shutdown_event is not None: - shutdown_trigger = partial(check_multiprocess_shutdown_event, shutdown_event, asyncio.sleep) - - _run( - partial(worker_serve, app, config, sockets=sockets), - debug=config.debug, - shutdown_trigger=shutdown_trigger, - loop_factory=uvloop.new_event_loop, - ) - - -def _run( - main: Callable, - *, - debug: bool = False, - shutdown_trigger: Optional[Callable[..., Awaitable[None]]] = None, - loop_factory: Callable[[], asyncio.AbstractEventLoop] | None = None, -) -> None: - with Runner(debug=debug, loop_factory=loop_factory) as runner: - runner.get_loop().set_exception_handler(_exception_handler) - runner.run(main(shutdown_trigger=shutdown_trigger)) - - -def _exception_handler(loop: asyncio.AbstractEventLoop, context: dict) -> None: - exception = context.get("exception") - if isinstance(exception, ssl.SSLError): - pass # Handshake failure - else: - loop.default_exception_handler(context) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/statsd.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/statsd.py deleted file mode 100644 index cd2cafa..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/statsd.py +++ /dev/null @@ -1,26 +0,0 @@ -from __future__ import annotations - -import asyncio -from typing import Optional - -from ..config import Config -from ..statsd import StatsdLogger as Base - - -class _DummyProto(asyncio.DatagramProtocol): - pass - - -class StatsdLogger(Base): - def __init__(self, config: Config) -> None: - super().__init__(config) - self.address = config.statsd_host.rsplit(":", 1) - self.transport: Optional[asyncio.BaseTransport] = None - - async def _socket_send(self, message: bytes) -> None: - if self.transport is None: - self.transport, _ = await asyncio.get_event_loop().create_datagram_endpoint( - _DummyProto, remote_addr=(self.address[0], int(self.address[1])) - ) - - self.transport.sendto(message) # type: ignore diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/task_group.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/task_group.py deleted file mode 100644 index 2e58903..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/task_group.py +++ /dev/null @@ -1,74 +0,0 @@ -from __future__ import annotations - -import asyncio -from functools import partial -from types import TracebackType -from typing import Any, Awaitable, Callable, Optional - -from ..config import Config -from ..typing import AppWrapper, ASGIReceiveCallable, ASGIReceiveEvent, ASGISendEvent, Scope - -try: - from asyncio import TaskGroup as AsyncioTaskGroup -except ImportError: - from taskgroup import TaskGroup as AsyncioTaskGroup # type: ignore - - -async def _handle( - app: AppWrapper, - config: Config, - scope: Scope, - receive: ASGIReceiveCallable, - send: Callable[[Optional[ASGISendEvent]], Awaitable[None]], - sync_spawn: Callable, - call_soon: Callable, -) -> None: - try: - await app(scope, receive, send, sync_spawn, call_soon) - except asyncio.CancelledError: - raise - except Exception: - await config.log.exception("Error in ASGI Framework") - finally: - await send(None) - - -class TaskGroup: - def __init__(self, loop: asyncio.AbstractEventLoop) -> None: - self._loop = loop - self._task_group = AsyncioTaskGroup() - - async def spawn_app( - self, - app: AppWrapper, - config: Config, - scope: Scope, - send: Callable[[Optional[ASGISendEvent]], Awaitable[None]], - ) -> Callable[[ASGIReceiveEvent], Awaitable[None]]: - app_queue: asyncio.Queue[ASGIReceiveEvent] = asyncio.Queue(config.max_app_queue_size) - - def _call_soon(func: Callable, *args: Any) -> Any: - future = asyncio.run_coroutine_threadsafe(func(*args), self._loop) - return future.result() - - self.spawn( - _handle, - app, - config, - scope, - app_queue.get, - send, - partial(self._loop.run_in_executor, None), - _call_soon, - ) - return app_queue.put - - def spawn(self, func: Callable, *args: Any) -> None: - self._task_group.create_task(func(*args)) - - async def __aenter__(self) -> "TaskGroup": - await self._task_group.__aenter__() - return self - - async def __aexit__(self, exc_type: type, exc_value: BaseException, tb: TracebackType) -> None: - await self._task_group.__aexit__(exc_type, exc_value, tb) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/tcp_server.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/tcp_server.py deleted file mode 100644 index bf9d9fe..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/tcp_server.py +++ /dev/null @@ -1,140 +0,0 @@ -from __future__ import annotations - -import asyncio -from ssl import SSLError -from typing import Any, Generator - -from .task_group import TaskGroup -from .worker_context import AsyncioSingleTask, WorkerContext -from ..config import Config -from ..events import Closed, Event, RawData, Updated -from ..protocol import ProtocolWrapper -from ..typing import AppWrapper, ConnectionState, LifespanState -from ..utils import parse_socket_addr - -MAX_RECV = 2**16 - - -class TCPServer: - def __init__( - self, - app: AppWrapper, - loop: asyncio.AbstractEventLoop, - config: Config, - context: WorkerContext, - state: LifespanState, - reader: asyncio.StreamReader, - writer: asyncio.StreamWriter, - ) -> None: - self.app = app - self.config = config - self.context = context - self.loop = loop - self.protocol: ProtocolWrapper - self.reader = reader - self.writer = writer - self.send_lock = asyncio.Lock() - self.state = state - self.idle_task = AsyncioSingleTask() - - def __await__(self) -> Generator[Any, None, None]: - return self.run().__await__() - - async def run(self) -> None: - socket = self.writer.get_extra_info("socket") - try: - client = parse_socket_addr(socket.family, socket.getpeername()) - server = parse_socket_addr(socket.family, socket.getsockname()) - ssl_object = self.writer.get_extra_info("ssl_object") - if ssl_object is not None: - ssl = True - alpn_protocol = ssl_object.selected_alpn_protocol() - else: - ssl = False - alpn_protocol = "http/1.1" - - async with TaskGroup(self.loop) as task_group: - self._task_group = task_group - self.protocol = ProtocolWrapper( - self.app, - self.config, - self.context, - task_group, - ConnectionState(self.state.copy()), - ssl, - client, - server, - self.protocol_send, - alpn_protocol, - ) - await self.protocol.initiate() - await self.idle_task.restart(task_group, self._idle_timeout) - await self._read_data() - except OSError: - pass - finally: - await self._close() - - async def protocol_send(self, event: Event) -> None: - if isinstance(event, RawData): - async with self.send_lock: - try: - self.writer.write(event.data) - await self.writer.drain() - except (ConnectionError, RuntimeError): - await self.protocol.handle(Closed()) - elif isinstance(event, Closed): - await self._close() - elif isinstance(event, Updated): - if event.idle: - await self.idle_task.restart(self._task_group, self._idle_timeout) - else: - await self.idle_task.stop() - - async def _read_data(self) -> None: - while not self.reader.at_eof(): - try: - data = await asyncio.wait_for(self.reader.read(MAX_RECV), self.config.read_timeout) - except ( - ConnectionError, - OSError, - asyncio.TimeoutError, - TimeoutError, - SSLError, - ): - break - else: - await self.protocol.handle(RawData(data)) - - await self.protocol.handle(Closed()) - - async def _close(self) -> None: - try: - self.writer.write_eof() - except (NotImplementedError, OSError, RuntimeError): - pass # Likely SSL connection - - try: - self.writer.close() - await self.writer.wait_closed() - except ( - BrokenPipeError, - ConnectionAbortedError, - ConnectionResetError, - RuntimeError, - asyncio.CancelledError, - ): - pass # Already closed - finally: - await self.idle_task.stop() - - async def _initiate_server_close(self) -> None: - await self.protocol.handle(Closed()) - self.writer.close() - - async def _idle_timeout(self) -> None: - try: - await asyncio.wait_for(self.context.terminated.wait(), self.config.keep_alive_timeout) - except asyncio.TimeoutError: - pass - await asyncio.shield(self._initiate_server_close()) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/udp_server.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/udp_server.py deleted file mode 100644 index 32857cc..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/udp_server.py +++ /dev/null @@ -1,68 +0,0 @@ -from __future__ import annotations - -import asyncio -from typing import Optional, Tuple, TYPE_CHECKING - -from .task_group import TaskGroup -from .worker_context import WorkerContext -from ..config import Config -from ..events import Event, RawData -from ..typing import AppWrapper, ConnectionState, LifespanState -from ..utils import parse_socket_addr - -if TYPE_CHECKING: - # h3/Quic is an optional part of Hypercorn - from ..protocol.quic import QuicProtocol # noqa: F401 - - -class UDPServer(asyncio.DatagramProtocol): - def __init__( - self, - app: AppWrapper, - loop: asyncio.AbstractEventLoop, - config: Config, - context: WorkerContext, - state: LifespanState, - ) -> None: - self.app = app - self.config = config - self.context = context - self.loop = loop - self.protocol: "QuicProtocol" - self.protocol_queue: asyncio.Queue = asyncio.Queue(10) - self.transport: Optional[asyncio.DatagramTransport] = None - self.state = state - - def connection_made(self, transport: asyncio.DatagramTransport) -> None: # type: ignore - self.transport = transport - - def datagram_received(self, data: bytes, address: Tuple[bytes, str]) -> None: # type: ignore - try: - self.protocol_queue.put_nowait(RawData(data=data, address=address)) # type: ignore - except asyncio.QueueFull: - pass # Just throw the data away, is UDP - - async def run(self) -> None: - # h3/Quic is an optional part of Hypercorn - from ..protocol.quic import QuicProtocol # noqa: F811 - - socket = self.transport.get_extra_info("socket") - server = parse_socket_addr(socket.family, socket.getsockname()) - async with TaskGroup(self.loop) as task_group: - self.protocol = QuicProtocol( - self.app, - self.config, - self.context, - task_group, - ConnectionState(self.state.copy()), - server, - self.protocol_send, - ) - - while not self.context.terminated.is_set() or not self.protocol.idle: - event = await self.protocol_queue.get() - await self.protocol.handle(event) - - async def protocol_send(self, event: Event) -> None: - if isinstance(event, RawData): - self.transport.sendto(event.data, event.address) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/worker_context.py b/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/worker_context.py deleted file mode 100644 index 31e9877..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/asyncio/worker_context.py +++ /dev/null @@ -1,78 +0,0 @@ -from __future__ import annotations - -import asyncio -from typing import Callable, Optional, Type, Union - -from ..typing import Event, SingleTask, TaskGroup - - -class AsyncioSingleTask: - def __init__(self) -> None: - self._handle: Optional[asyncio.Task] = None - self._lock = asyncio.Lock() - - async def restart(self, task_group: TaskGroup, action: Callable) -> None: - async with self._lock: - if self._handle is not None: - self._handle.cancel() - try: - await self._handle - except asyncio.CancelledError: - pass - - self._handle = task_group._task_group.create_task(action()) # type: ignore - - async def stop(self) -> None: - async with self._lock: - if self._handle is not None: - self._handle.cancel() - try: - await self._handle - except asyncio.CancelledError: - pass - - self._handle = None - - -class EventWrapper: - def __init__(self) -> None: - self._event = asyncio.Event() - - async def clear(self) -> None: - self._event.clear() - - async def wait(self) -> None: - await self._event.wait() - - async def set(self) -> None: - self._event.set() - - def is_set(self) -> bool: - return self._event.is_set() - - -class WorkerContext: - event_class: Type[Event] = EventWrapper - single_task_class: Type[SingleTask] = AsyncioSingleTask - - def __init__(self, max_requests: Optional[int]) -> None: - self.max_requests = max_requests - self.requests = 0 - self.terminate = self.event_class() - self.terminated = self.event_class() - - async def mark_request(self) -> None: - if self.max_requests is None: - return - - self.requests += 1 - if self.requests > self.max_requests: - await self.terminate.set() - - @staticmethod - async def sleep(wait: Union[float, int]) -> None: - return await asyncio.sleep(wait) - - @staticmethod - def time() -> float: - return asyncio.get_event_loop().time() diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/config.py b/serverenv/lib/python3.9/site-packages/hypercorn/config.py deleted file mode 100644 index 71d5b2e..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/config.py +++ /dev/null @@ -1,408 +0,0 @@ -from __future__ import annotations - -import importlib -import importlib.util -import logging -import os -import socket -import stat -import sys -import types -import warnings -from dataclasses import dataclass -from ssl import ( - create_default_context, - OP_NO_COMPRESSION, - Purpose, - SSLContext, - TLSVersion, - VerifyFlags, - VerifyMode, -) -from time import time -from typing import Any, AnyStr, Dict, List, Mapping, Optional, Tuple, Type, Union -from wsgiref.handlers import format_date_time - -if sys.version_info >= (3, 11): - import tomllib -else: - import tomli as tomllib - -from .logging import Logger - -BYTES = 1 -OCTETS = 1 -SECONDS = 1.0 - -FilePath = Union[AnyStr, os.PathLike] -SocketKind = Union[int, socket.SocketKind] - - -@dataclass -class Sockets: - secure_sockets: List[socket.socket] - insecure_sockets: List[socket.socket] - quic_sockets: List[socket.socket] - - -class SocketTypeError(Exception): - def __init__(self, expected: SocketKind, actual: SocketKind) -> None: - super().__init__( - f'Unexpected socket type, wanted "{socket.SocketKind(expected)}" got ' - f'"{socket.SocketKind(actual)}"' - ) - - -class Config: - _bind = ["127.0.0.1:8000"] - _insecure_bind: List[str] = [] - _quic_bind: List[str] = [] - _quic_addresses: List[Tuple] = [] - _log: Optional[Logger] = None - _root_path: str = "" - - access_log_format = '%(h)s %(l)s %(l)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' - accesslog: Union[logging.Logger, str, None] = None - alpn_protocols = ["h2", "http/1.1"] - alt_svc_headers: List[str] = [] - application_path: str - backlog = 100 - ca_certs: Optional[str] = None - certfile: Optional[str] = None - ciphers: str = "ECDHE+AESGCM" - debug = False - dogstatsd_tags = "" - errorlog: Union[logging.Logger, str, None] = "-" - graceful_timeout: float = 3 * SECONDS - read_timeout: Optional[int] = None - group: Optional[int] = None - h11_max_incomplete_size = 16 * 1024 * BYTES - h11_pass_raw_headers = False - h2_max_concurrent_streams = 100 - h2_max_header_list_size = 2**16 - h2_max_inbound_frame_size = 2**14 * OCTETS - include_date_header = True - include_server_header = True - keep_alive_timeout = 5 * SECONDS - keep_alive_max_requests = 1000 - keyfile: Optional[str] = None - keyfile_password: Optional[str] = None - logconfig: Optional[str] = None - logconfig_dict: Optional[dict] = None - logger_class = Logger - loglevel: str = "INFO" - max_app_queue_size: int = 10 - max_requests: Optional[int] = None - max_requests_jitter: int = 0 - pid_path: Optional[str] = None - server_names: List[str] = [] - shutdown_timeout = 60 * SECONDS - ssl_handshake_timeout = 60 * SECONDS - startup_timeout = 60 * SECONDS - statsd_host: Optional[str] = None - statsd_prefix = "" - umask: Optional[int] = None - use_reloader = False - user: Optional[int] = None - verify_flags: Optional[VerifyFlags] = None - verify_mode: Optional[VerifyMode] = None - websocket_max_message_size = 16 * 1024 * 1024 * BYTES - websocket_ping_interval: Optional[float] = None - worker_class = "asyncio" - workers = 1 - wsgi_max_body_size = 16 * 1024 * 1024 * BYTES - - def set_cert_reqs(self, value: int) -> None: - warnings.warn("Please use verify_mode instead", Warning) - self.verify_mode = VerifyMode(value) - - cert_reqs = property(None, set_cert_reqs) - - @property - def log(self) -> Logger: - if self._log is None: - self._log = self.logger_class(self) - return self._log - - @property - def bind(self) -> List[str]: - return self._bind - - @bind.setter - def bind(self, value: Union[List[str], str]) -> None: - if isinstance(value, str): - self._bind = [value] - else: - self._bind = value - - @property - def insecure_bind(self) -> List[str]: - return self._insecure_bind - - @insecure_bind.setter - def insecure_bind(self, value: Union[List[str], str]) -> None: - if isinstance(value, str): - self._insecure_bind = [value] - else: - self._insecure_bind = value - - @property - def quic_bind(self) -> List[str]: - return self._quic_bind - - @quic_bind.setter - def quic_bind(self, value: Union[List[str], str]) -> None: - if isinstance(value, str): - self._quic_bind = [value] - else: - self._quic_bind = value - - @property - def root_path(self) -> str: - return self._root_path - - @root_path.setter - def root_path(self, value: str) -> None: - self._root_path = value.rstrip("/") - - def create_ssl_context(self) -> Optional[SSLContext]: - if not self.ssl_enabled: - return None - - context = create_default_context(Purpose.CLIENT_AUTH) - context.set_ciphers(self.ciphers) - context.minimum_version = TLSVersion.TLSv1_2 # RFC 7540 Section 9.2: MUST be TLS >=1.2 - context.options = OP_NO_COMPRESSION # RFC 7540 Section 9.2.1: MUST disable compression - context.set_alpn_protocols(self.alpn_protocols) - - if self.certfile is not None and self.keyfile is not None: - context.load_cert_chain( - certfile=self.certfile, - keyfile=self.keyfile, - password=self.keyfile_password, - ) - - if self.ca_certs is not None: - context.load_verify_locations(self.ca_certs) - if self.verify_mode is not None: - context.verify_mode = self.verify_mode - if self.verify_flags is not None: - context.verify_flags = self.verify_flags - - return context - - @property - def ssl_enabled(self) -> bool: - return self.certfile is not None and self.keyfile is not None - - def create_sockets(self) -> Sockets: - if self.ssl_enabled: - secure_sockets = self._create_sockets(self.bind) - insecure_sockets = self._create_sockets(self.insecure_bind) - quic_sockets = self._create_sockets(self.quic_bind, socket.SOCK_DGRAM) - self._set_quic_addresses(quic_sockets) - else: - secure_sockets = [] - insecure_sockets = self._create_sockets(self.bind) - quic_sockets = [] - return Sockets(secure_sockets, insecure_sockets, quic_sockets) - - def _set_quic_addresses(self, sockets: List[socket.socket]) -> None: - self._quic_addresses = [] - for sock in sockets: - name = sock.getsockname() - if type(name) is not str and len(name) >= 2: - self._quic_addresses.append(name) - else: - warnings.warn( - f'Cannot create a alt-svc header for the QUIC socket with address "{name}"', - Warning, - ) - - def _create_sockets( - self, binds: List[str], type_: int = socket.SOCK_STREAM - ) -> List[socket.socket]: - sockets: List[socket.socket] = [] - for bind in binds: - binding: Any = None - if bind.startswith("unix:"): - sock = socket.socket(socket.AF_UNIX, type_) - binding = bind[5:] - try: - if stat.S_ISSOCK(os.stat(binding).st_mode): - os.remove(binding) - except FileNotFoundError: - pass - elif bind.startswith("fd://"): - sock = socket.socket(fileno=int(bind[5:])) - actual_type = sock.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE) - if actual_type != type_: - raise SocketTypeError(type_, actual_type) - else: - bind = bind.replace("[", "").replace("]", "") - try: - value = bind.rsplit(":", 1) - host, port = value[0], int(value[1]) - except (ValueError, IndexError): - host, port = bind, 8000 - sock = socket.socket(socket.AF_INET6 if ":" in host else socket.AF_INET, type_) - - if type_ == socket.SOCK_STREAM: - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - - if self.workers > 1: - try: - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) - except AttributeError: - pass - binding = (host, port) - - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - if bind.startswith("unix:"): - if self.umask is not None: - current_umask = os.umask(self.umask) - sock.bind(binding) - if self.user is not None and self.group is not None: - os.chown(binding, self.user, self.group) - if self.umask is not None: - os.umask(current_umask) - elif bind.startswith("fd://"): - pass - else: - sock.bind(binding) - - sock.setblocking(False) - try: - sock.set_inheritable(True) - except AttributeError: - pass - sockets.append(sock) - return sockets - - def response_headers(self, protocol: str) -> List[Tuple[bytes, bytes]]: - headers = [] - if self.include_date_header: - headers.append((b"date", format_date_time(time()).encode("ascii"))) - if self.include_server_header: - headers.append((b"server", f"hypercorn-{protocol}".encode("ascii"))) - - for alt_svc_header in self.alt_svc_headers: - headers.append((b"alt-svc", alt_svc_header.encode())) - if len(self.alt_svc_headers) == 0 and self._quic_addresses: - from aioquic.h3.connection import H3_ALPN - - for version in H3_ALPN: - for addr in self._quic_addresses: - port = addr[1] - headers.append((b"alt-svc", b'%s=":%d"; ma=3600' % (version.encode(), port))) - - return headers - - def set_statsd_logger_class(self, statsd_logger: Type[Logger]) -> None: - if self.logger_class == Logger and self.statsd_host is not None: - self.logger_class = statsd_logger - - @classmethod - def from_mapping( - cls: Type["Config"], mapping: Optional[Mapping[str, Any]] = None, **kwargs: Any - ) -> "Config": - """Create a configuration from a mapping. - - This allows either a mapping to be directly passed or as - keyword arguments, for example, - - .. code-block:: python - - config = {'keep_alive_timeout': 10} - Config.from_mapping(config) - Config.from_mapping(keep_alive_timeout=10) - - Arguments: - mapping: Optionally a mapping object. - kwargs: Optionally a collection of keyword arguments to - form a mapping. - """ - mappings: Dict[str, Any] = {} - if mapping is not None: - mappings.update(mapping) - mappings.update(kwargs) - config = cls() - for key, value in mappings.items(): - try: - setattr(config, key, value) - except AttributeError: - pass - - return config - - @classmethod - def from_pyfile(cls: Type["Config"], filename: FilePath) -> "Config": - """Create a configuration from a Python file. - - .. code-block:: python - - Config.from_pyfile('hypercorn_config.py') - - Arguments: - filename: The filename which gives the path to the file. - """ - file_path = os.fspath(filename) - spec = importlib.util.spec_from_file_location("module.name", file_path) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - return cls.from_object(module) - - @classmethod - def from_toml(cls: Type["Config"], filename: FilePath) -> "Config": - """Load the configuration values from a TOML formatted file. - - This allows configuration to be loaded as so - - .. code-block:: python - - Config.from_toml('config.toml') - - Arguments: - filename: The filename which gives the path to the file. - """ - file_path = os.fspath(filename) - with open(file_path, "rb") as file_: - data = tomllib.load(file_) - return cls.from_mapping(data) - - @classmethod - def from_object(cls: Type["Config"], instance: Union[object, str]) -> "Config": - """Create a configuration from a Python object. - - This can be used to reference modules or objects within - modules for example, - - .. code-block:: python - - Config.from_object('module') - Config.from_object('module.instance') - from module import instance - Config.from_object(instance) - - are valid. - - Arguments: - instance: Either a str referencing a python object or the - object itself. - - """ - if isinstance(instance, str): - try: - instance = importlib.import_module(instance) - except ImportError: - path, config = instance.rsplit(".", 1) - module = importlib.import_module(path) - instance = getattr(module, config) - - mapping = { - key: getattr(instance, key) - for key in dir(instance) - if not isinstance(getattr(instance, key), types.ModuleType) and not key.startswith("__") - } - return cls.from_mapping(mapping) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/events.py b/serverenv/lib/python3.9/site-packages/hypercorn/events.py deleted file mode 100644 index e829616..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/events.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import annotations - -from abc import ABC -from dataclasses import dataclass -from typing import Optional, Tuple - - -class Event(ABC): - pass - - -@dataclass(frozen=True) -class RawData(Event): - data: bytes - address: Optional[Tuple[str, int]] = None - - -@dataclass(frozen=True) -class Closed(Event): - pass - - -@dataclass(frozen=True) -class Updated(Event): - idle: bool diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/logging.py b/serverenv/lib/python3.9/site-packages/hypercorn/logging.py deleted file mode 100644 index d9b8901..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/logging.py +++ /dev/null @@ -1,202 +0,0 @@ -from __future__ import annotations - -import json -import logging -import os -import sys -import time -from http import HTTPStatus -from logging.config import dictConfig, fileConfig -from typing import Any, IO, Mapping, Optional, TYPE_CHECKING, Union - -if sys.version_info >= (3, 11): - import tomllib -else: - import tomli as tomllib - - -if TYPE_CHECKING: - from .config import Config - from .typing import ResponseSummary, WWWScope - - -def _create_logger( - name: str, - target: Union[logging.Logger, str, None], - level: Optional[str], - sys_default: IO, - *, - propagate: bool = True, -) -> Optional[logging.Logger]: - if isinstance(target, logging.Logger): - return target - - if target: - logger = logging.getLogger(name) - logger.handlers = [ - logging.StreamHandler(sys_default) if target == "-" else logging.FileHandler(target) # type: ignore # noqa: E501 - ] - logger.propagate = propagate - formatter = logging.Formatter( - "%(asctime)s [%(process)d] [%(levelname)s] %(message)s", - "[%Y-%m-%d %H:%M:%S %z]", - ) - logger.handlers[0].setFormatter(formatter) - if level is not None: - logger.setLevel(logging.getLevelName(level.upper())) - return logger - else: - return None - - -class Logger: - def __init__(self, config: "Config") -> None: - self.access_log_format = config.access_log_format - - self.access_logger = _create_logger( - "hypercorn.access", - config.accesslog, - config.loglevel, - sys.stdout, - propagate=False, - ) - self.error_logger = _create_logger( - "hypercorn.error", config.errorlog, config.loglevel, sys.stderr - ) - - if config.logconfig is not None: - if config.logconfig.startswith("json:"): - with open(config.logconfig[5:]) as file_: - dictConfig(json.load(file_)) - elif config.logconfig.startswith("toml:"): - with open(config.logconfig[5:], "rb") as file_: - dictConfig(tomllib.load(file_)) - else: - log_config = { - "__file__": config.logconfig, - "here": os.path.dirname(config.logconfig), - } - fileConfig(config.logconfig, defaults=log_config, disable_existing_loggers=False) - else: - if config.logconfig_dict is not None: - dictConfig(config.logconfig_dict) - - async def access( - self, request: "WWWScope", response: "ResponseSummary", request_time: float - ) -> None: - if self.access_logger is not None: - self.access_logger.info( - self.access_log_format, self.atoms(request, response, request_time) - ) - - async def critical(self, message: str, *args: Any, **kwargs: Any) -> None: - if self.error_logger is not None: - self.error_logger.critical(message, *args, **kwargs) - - async def error(self, message: str, *args: Any, **kwargs: Any) -> None: - if self.error_logger is not None: - self.error_logger.error(message, *args, **kwargs) - - async def warning(self, message: str, *args: Any, **kwargs: Any) -> None: - if self.error_logger is not None: - self.error_logger.warning(message, *args, **kwargs) - - async def info(self, message: str, *args: Any, **kwargs: Any) -> None: - if self.error_logger is not None: - self.error_logger.info(message, *args, **kwargs) - - async def debug(self, message: str, *args: Any, **kwargs: Any) -> None: - if self.error_logger is not None: - self.error_logger.debug(message, *args, **kwargs) - - async def exception(self, message: str, *args: Any, **kwargs: Any) -> None: - if self.error_logger is not None: - self.error_logger.exception(message, *args, **kwargs) - - async def log(self, level: int, message: str, *args: Any, **kwargs: Any) -> None: - if self.error_logger is not None: - self.error_logger.log(level, message, *args, **kwargs) - - def atoms( - self, request: "WWWScope", response: Optional["ResponseSummary"], request_time: float - ) -> Mapping[str, str]: - """Create and return an access log atoms dictionary. - - This can be overidden and customised if desired. It should - return a mapping between an access log format key and a value. - """ - return AccessLogAtoms(request, response, request_time) - - def __getattr__(self, name: str) -> Any: - return getattr(self.error_logger, name) - - -class AccessLogAtoms(dict): - def __init__( - self, request: "WWWScope", response: Optional["ResponseSummary"], request_time: float - ) -> None: - for name, value in request["headers"]: - self[f"{{{name.decode('latin1').lower()}}}i"] = value.decode("latin1") - for name, value in os.environ.items(): - self[f"{{{name.lower()}}}e"] = value - protocol = request.get("http_version", "ws") - client = request.get("client") - if client is None: - remote_addr = None - elif len(client) == 2: - remote_addr = f"{client[0]}:{client[1]}" - elif len(client) == 1: - remote_addr = client[0] - else: # make sure not to throw UnboundLocalError - remote_addr = f"" - if request["type"] == "http": - method = request["method"] - else: - method = "GET" - query_string = request["query_string"].decode() - path_with_qs = request["path"] + ("?" + query_string if query_string else "") - - status_code = "-" - status_phrase = "-" - if response is not None: - for name, value in response.get("headers", []): # type: ignore - self[f"{{{name.decode('latin1').lower()}}}o"] = value.decode("latin1") # type: ignore # noqa: E501 - status_code = str(response["status"]) - try: - status_phrase = HTTPStatus(response["status"]).phrase - except ValueError: - status_phrase = f"" - self.update( - { - "h": remote_addr, - "l": "-", - "t": time.strftime("[%d/%b/%Y:%H:%M:%S %z]"), - "r": f"{method} {request['path']} {protocol}", - "R": f"{method} {path_with_qs} {protocol}", - "s": status_code, - "st": status_phrase, - "S": request["scheme"], - "m": method, - "U": request["path"], - "Uq": path_with_qs, - "q": query_string, - "H": protocol, - "b": self["{Content-Length}o"], - "B": self["{Content-Length}o"], - "f": self["{Referer}i"], - "a": self["{User-Agent}i"], - "T": int(request_time), - "D": int(request_time * 1_000_000), - "L": f"{request_time:.6f}", - "p": f"<{os.getpid()}>", - } - ) - - def __getitem__(self, key: str) -> str: - try: - if key.startswith("{"): - return super().__getitem__(key.lower()) - else: - return super().__getitem__(key) - except KeyError: - return "-" diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/__init__.py b/serverenv/lib/python3.9/site-packages/hypercorn/middleware/__init__.py deleted file mode 100644 index e7f017c..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import annotations - -from .dispatcher import DispatcherMiddleware -from .http_to_https import HTTPToHTTPSRedirectMiddleware -from .proxy_fix import ProxyFixMiddleware -from .wsgi import AsyncioWSGIMiddleware, TrioWSGIMiddleware - -__all__ = ( - "AsyncioWSGIMiddleware", - "DispatcherMiddleware", - "HTTPToHTTPSRedirectMiddleware", - "ProxyFixMiddleware", - "TrioWSGIMiddleware", -) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/dispatcher.py b/serverenv/lib/python3.9/site-packages/hypercorn/middleware/dispatcher.py deleted file mode 100644 index 009541b..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/dispatcher.py +++ /dev/null @@ -1,108 +0,0 @@ -from __future__ import annotations - -import asyncio -from functools import partial -from typing import Callable, Dict - -from ..asyncio.task_group import TaskGroup -from ..typing import ASGIFramework, Scope - -MAX_QUEUE_SIZE = 10 - - -class _DispatcherMiddleware: - def __init__(self, mounts: Dict[str, ASGIFramework]) -> None: - self.mounts = mounts - - async def __call__(self, scope: Scope, receive: Callable, send: Callable) -> None: - if scope["type"] == "lifespan": - await self._handle_lifespan(scope, receive, send) - else: - for path, app in self.mounts.items(): - if scope["path"].startswith(path): - scope["path"] = scope["path"][len(path) :] or "/" - return await app(scope, receive, send) - await send( - { - "type": "http.response.start", - "status": 404, - "headers": [(b"content-length", b"0")], - } - ) - await send({"type": "http.response.body"}) - - async def _handle_lifespan(self, scope: Scope, receive: Callable, send: Callable) -> None: - pass - - -class AsyncioDispatcherMiddleware(_DispatcherMiddleware): - async def _handle_lifespan(self, scope: Scope, receive: Callable, send: Callable) -> None: - self.app_queues: Dict[str, asyncio.Queue] = { - path: asyncio.Queue(MAX_QUEUE_SIZE) for path in self.mounts - } - self.startup_complete = {path: False for path in self.mounts} - self.shutdown_complete = {path: False for path in self.mounts} - - async with TaskGroup(asyncio.get_event_loop()) as task_group: - for path, app in self.mounts.items(): - task_group.spawn( - app, - scope, - self.app_queues[path].get, - partial(self.send, path, send), - ) - - while True: - message = await receive() - for queue in self.app_queues.values(): - await queue.put(message) - if message["type"] == "lifespan.shutdown": - break - - async def send(self, path: str, send: Callable, message: dict) -> None: - if message["type"] == "lifespan.startup.complete": - self.startup_complete[path] = True - if all(self.startup_complete.values()): - await send({"type": "lifespan.startup.complete"}) - elif message["type"] == "lifespan.shutdown.complete": - self.shutdown_complete[path] = True - if all(self.shutdown_complete.values()): - await send({"type": "lifespan.shutdown.complete"}) - - -class TrioDispatcherMiddleware(_DispatcherMiddleware): - async def _handle_lifespan(self, scope: Scope, receive: Callable, send: Callable) -> None: - import trio - - self.app_queues = {path: trio.open_memory_channel(MAX_QUEUE_SIZE) for path in self.mounts} - self.startup_complete = {path: False for path in self.mounts} - self.shutdown_complete = {path: False for path in self.mounts} - - async with trio.open_nursery() as nursery: - for path, app in self.mounts.items(): - nursery.start_soon( - app, - scope, - self.app_queues[path][1].receive, - partial(self.send, path, send), - ) - - while True: - message = await receive() - for channels in self.app_queues.values(): - await channels[0].send(message) - if message["type"] == "lifespan.shutdown": - break - - async def send(self, path: str, send: Callable, message: dict) -> None: - if message["type"] == "lifespan.startup.complete": - self.startup_complete[path] = True - if all(self.startup_complete.values()): - await send({"type": "lifespan.startup.complete"}) - elif message["type"] == "lifespan.shutdown.complete": - self.shutdown_complete[path] = True - if all(self.shutdown_complete.values()): - await send({"type": "lifespan.shutdown.complete"}) - - -DispatcherMiddleware = AsyncioDispatcherMiddleware # Remove with version 0.11 diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/http_to_https.py b/serverenv/lib/python3.9/site-packages/hypercorn/middleware/http_to_https.py deleted file mode 100644 index 542b28f..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/http_to_https.py +++ /dev/null @@ -1,67 +0,0 @@ -from __future__ import annotations - -from typing import Callable, Optional -from urllib.parse import urlunsplit - -from ..typing import ASGIFramework, HTTPScope, Scope, WebsocketScope, WWWScope - - -class HTTPToHTTPSRedirectMiddleware: - def __init__(self, app: ASGIFramework, host: Optional[str]) -> None: - self.app = app - self.host = host - - async def __call__(self, scope: Scope, receive: Callable, send: Callable) -> None: - if scope["type"] == "http" and scope["scheme"] == "http": - await self._send_http_redirect(scope, send) - elif scope["type"] == "websocket" and scope["scheme"] == "ws": - # If the server supports the WebSocket Denial Response - # extension we can send a redirection response, if not we - # can only deny the WebSocket connection. - if "websocket.http.response" in scope.get("extensions", {}): - await self._send_websocket_redirect(scope, send) - else: - await send({"type": "websocket.close"}) - else: - return await self.app(scope, receive, send) - - async def _send_http_redirect(self, scope: HTTPScope, send: Callable) -> None: - new_url = self._new_url("https", scope) - await send( - { - "type": "http.response.start", - "status": 307, - "headers": [(b"location", new_url.encode())], - } - ) - await send({"type": "http.response.body"}) - - async def _send_websocket_redirect(self, scope: WebsocketScope, send: Callable) -> None: - # If the HTTP version is 2 we should redirect with a https - # scheme not wss. - scheme = "wss" - if scope.get("http_version", "1.1") == "2": - scheme = "https" - - new_url = self._new_url(scheme, scope) - await send( - { - "type": "websocket.http.response.start", - "status": 307, - "headers": [(b"location", new_url.encode())], - } - ) - await send({"type": "websocket.http.response.body"}) - - def _new_url(self, scheme: str, scope: WWWScope) -> str: - host = self.host - if host is None: - for key, value in scope["headers"]: - if key == b"host": - host = value.decode("latin-1") - break - if host is None: - raise ValueError("Host to redirect to cannot be determined") - - path = scope.get("root_path", "") + scope["raw_path"].decode() - return urlunsplit((scheme, host, path, scope["query_string"].decode(), "")) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/proxy_fix.py b/serverenv/lib/python3.9/site-packages/hypercorn/middleware/proxy_fix.py deleted file mode 100644 index bd3dc4c..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/proxy_fix.py +++ /dev/null @@ -1,79 +0,0 @@ -from __future__ import annotations - -from copy import deepcopy -from typing import Callable, Iterable, Literal, Optional, Tuple - -from ..typing import ASGIFramework, Scope - - -class ProxyFixMiddleware: - def __init__( - self, - app: ASGIFramework, - mode: Literal["legacy", "modern"] = "legacy", - trusted_hops: int = 1, - ) -> None: - self.app = app - self.mode = mode - self.trusted_hops = trusted_hops - - async def __call__(self, scope: Scope, receive: Callable, send: Callable) -> None: - # Keep the `or` instead of `in {'http' …}` to allow type narrowing - if scope["type"] == "http" or scope["type"] == "websocket": - scope = deepcopy(scope) - headers = scope["headers"] - client: Optional[str] = None - scheme: Optional[str] = None - host: Optional[str] = None - - if ( - self.mode == "modern" - and (value := _get_trusted_value(b"forwarded", headers, self.trusted_hops)) - is not None - ): - for part in value.split(";"): - if part.startswith("for="): - client = part[4:].strip() - elif part.startswith("host="): - host = part[5:].strip() - elif part.startswith("proto="): - scheme = part[6:].strip() - - else: - client = _get_trusted_value(b"x-forwarded-for", headers, self.trusted_hops) - scheme = _get_trusted_value(b"x-forwarded-proto", headers, self.trusted_hops) - host = _get_trusted_value(b"x-forwarded-host", headers, self.trusted_hops) - - if client is not None: - scope["client"] = (client, 0) - - if scheme is not None: - scope["scheme"] = scheme - - if host is not None: - headers = [ - (name, header_value) - for name, header_value in headers - if name.lower() != b"host" - ] - headers.append((b"host", host.encode())) - scope["headers"] = headers - - await self.app(scope, receive, send) - - -def _get_trusted_value( - name: bytes, headers: Iterable[Tuple[bytes, bytes]], trusted_hops: int -) -> Optional[str]: - if trusted_hops == 0: - return None - - values = [] - for header_name, header_value in headers: - if header_name.lower() == name: - values.extend([value.decode("latin1").strip() for value in header_value.split(b",")]) - - if len(values) >= trusted_hops: - return values[-trusted_hops] - - return None diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/wsgi.py b/serverenv/lib/python3.9/site-packages/hypercorn/middleware/wsgi.py deleted file mode 100644 index 8e4f61b..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/middleware/wsgi.py +++ /dev/null @@ -1,49 +0,0 @@ -from __future__ import annotations - -import asyncio -from functools import partial -from typing import Any, Callable, Iterable - -from ..app_wrappers import WSGIWrapper -from ..typing import ASGIReceiveCallable, ASGISendCallable, Scope, WSGIFramework - -MAX_BODY_SIZE = 2**16 - -WSGICallable = Callable[[dict, Callable], Iterable[bytes]] - - -class InvalidPathError(Exception): - pass - - -class _WSGIMiddleware: - def __init__(self, wsgi_app: WSGIFramework, max_body_size: int = MAX_BODY_SIZE) -> None: - self.wsgi_app = WSGIWrapper(wsgi_app, max_body_size) - self.max_body_size = max_body_size - - async def __call__( - self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable - ) -> None: - pass - - -class AsyncioWSGIMiddleware(_WSGIMiddleware): - async def __call__( - self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable - ) -> None: - loop = asyncio.get_event_loop() - - def _call_soon(func: Callable, *args: Any) -> Any: - future = asyncio.run_coroutine_threadsafe(func(*args), loop) - return future.result() - - await self.wsgi_app(scope, receive, send, partial(loop.run_in_executor, None), _call_soon) - - -class TrioWSGIMiddleware(_WSGIMiddleware): - async def __call__( - self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable - ) -> None: - import trio - - await self.wsgi_app(scope, receive, send, trio.to_thread.run_sync, trio.from_thread.run) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/__init__.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/__init__.py deleted file mode 100644 index 4e8feae..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/__init__.py +++ /dev/null @@ -1,96 +0,0 @@ -from __future__ import annotations - -from typing import Awaitable, Callable, Optional, Tuple, Union - -from .h2 import H2Protocol -from .h11 import H2CProtocolRequiredError, H2ProtocolAssumedError, H11Protocol -from ..config import Config -from ..events import Event, RawData -from ..typing import AppWrapper, ConnectionState, TaskGroup, WorkerContext - - -class ProtocolWrapper: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - task_group: TaskGroup, - state: ConnectionState, - ssl: bool, - client: Optional[Tuple[str, int]], - server: Optional[Tuple[str, int]], - send: Callable[[Event], Awaitable[None]], - alpn_protocol: Optional[str] = None, - ) -> None: - self.app = app - self.config = config - self.context = context - self.task_group = task_group - self.ssl = ssl - self.client = client - self.server = server - self.send = send - self.state = state - self.protocol: Union[H11Protocol, H2Protocol] - if alpn_protocol == "h2": - self.protocol = H2Protocol( - self.app, - self.config, - self.context, - self.task_group, - self.state, - self.ssl, - self.client, - self.server, - self.send, - ) - else: - self.protocol = H11Protocol( - self.app, - self.config, - self.context, - self.task_group, - self.state, - self.ssl, - self.client, - self.server, - self.send, - ) - - async def initiate(self) -> None: - return await self.protocol.initiate() - - async def handle(self, event: Event) -> None: - try: - return await self.protocol.handle(event) - except H2ProtocolAssumedError as error: - self.protocol = H2Protocol( - self.app, - self.config, - self.context, - self.task_group, - self.state, - self.ssl, - self.client, - self.server, - self.send, - ) - await self.protocol.initiate() - if error.data != b"": - return await self.protocol.handle(RawData(data=error.data)) - except H2CProtocolRequiredError as error: - self.protocol = H2Protocol( - self.app, - self.config, - self.context, - self.task_group, - self.state, - self.ssl, - self.client, - self.server, - self.send, - ) - await self.protocol.initiate(error.headers, error.settings) - if error.data != b"": - return await self.protocol.handle(RawData(data=error.data)) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/events.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/events.py deleted file mode 100644 index 0ded34a..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/events.py +++ /dev/null @@ -1,66 +0,0 @@ -from __future__ import annotations - -from dataclasses import dataclass -from typing import List, Tuple - -from hypercorn.typing import ConnectionState - - -@dataclass(frozen=True) -class Event: - stream_id: int - - -@dataclass(frozen=True) -class Request(Event): - headers: List[Tuple[bytes, bytes]] - http_version: str - method: str - raw_path: bytes - state: ConnectionState - - -@dataclass(frozen=True) -class Body(Event): - data: bytes - - -@dataclass(frozen=True) -class EndBody(Event): - pass - - -@dataclass(frozen=True) -class Trailers(Event): - headers: List[Tuple[bytes, bytes]] - - -@dataclass(frozen=True) -class Data(Event): - data: bytes - - -@dataclass(frozen=True) -class EndData(Event): - pass - - -@dataclass(frozen=True) -class Response(Event): - headers: List[Tuple[bytes, bytes]] - status_code: int - - -@dataclass(frozen=True) -class InformationalResponse(Event): - headers: List[Tuple[bytes, bytes]] - status_code: int - - def __post_init__(self) -> None: - if self.status_code >= 200 or self.status_code < 100: - raise ValueError(f"Status code must be 1XX not {self.status_code}") - - -@dataclass(frozen=True) -class StreamClosed(Event): - pass diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h11.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h11.py deleted file mode 100644 index c3c6e0f..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h11.py +++ /dev/null @@ -1,322 +0,0 @@ -from __future__ import annotations - -from itertools import chain -from typing import Awaitable, Callable, cast, Optional, Tuple, Type, Union - -import h11 - -from .events import ( - Body, - Data, - EndBody, - EndData, - Event as StreamEvent, - InformationalResponse, - Request, - Response, - StreamClosed, -) -from .http_stream import HTTPStream -from .ws_stream import WSStream -from ..config import Config -from ..events import Closed, Event, RawData, Updated -from ..typing import AppWrapper, ConnectionState, H11SendableEvent, TaskGroup, WorkerContext - -STREAM_ID = 1 - - -class H2CProtocolRequiredError(Exception): - def __init__(self, data: bytes, request: h11.Request) -> None: - settings = "" - headers = [(b":method", request.method), (b":path", request.target)] - for name, value in request.headers: - if name.lower() == b"http2-settings": - settings = value.decode() - elif name.lower() == b"host": - headers.append((b":authority", value)) - headers.append((name, value)) - - self.data = data - self.headers = headers - self.settings = settings - - -class H2ProtocolAssumedError(Exception): - def __init__(self, data: bytes) -> None: - self.data = data - - -class H11WSConnection: - # This class matches the h11 interface, and either passes data - # through without altering it (for Data, EndData) or sends h11 - # events (Response, Body, EndBody). - our_state = None # Prevents recycling the connection - they_are_waiting_for_100_continue = False - their_state = None - trailing_data = (b"", False) - - def __init__(self, h11_connection: h11.Connection) -> None: - self.buffer = bytearray(h11_connection.trailing_data[0]) - self.h11_connection = h11_connection - - def receive_data(self, data: bytes) -> None: - self.buffer.extend(data) - - def next_event(self) -> Union[Data, Type[h11.NEED_DATA]]: - if self.buffer: - event = Data(stream_id=STREAM_ID, data=bytes(self.buffer)) - self.buffer = bytearray() - return event - else: - return h11.NEED_DATA - - def send(self, event: H11SendableEvent) -> bytes: - return self.h11_connection.send(event) - - def start_next_cycle(self) -> None: - pass - - -class H11Protocol: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - task_group: TaskGroup, - connection_state: ConnectionState, - ssl: bool, - client: Optional[Tuple[str, int]], - server: Optional[Tuple[str, int]], - send: Callable[[Event], Awaitable[None]], - ) -> None: - self.app = app - self.can_read = context.event_class() - self.client = client - self.config = config - self.connection: Union[h11.Connection, H11WSConnection] = h11.Connection( - h11.SERVER, max_incomplete_event_size=self.config.h11_max_incomplete_size - ) - self.context = context - self.keep_alive_requests = 0 - self.send = send - self.server = server - self.ssl = ssl - self.stream: Optional[Union[HTTPStream, WSStream]] = None - self.task_group = task_group - self.connection_state = connection_state - - async def initiate(self) -> None: - pass - - async def handle(self, event: Event) -> None: - if isinstance(event, RawData): - self.connection.receive_data(event.data) - await self._handle_events() - elif isinstance(event, Closed): - if self.stream is not None: - await self._close_stream() - - async def stream_send(self, event: StreamEvent) -> None: - if isinstance(event, Response): - if event.status_code >= 200: - headers = list(chain(event.headers, self.config.response_headers("h11"))) - if self.keep_alive_requests >= self.config.keep_alive_max_requests: - headers.append((b"connection", b"close")) - await self._send_h11_event( - h11.Response( - headers=headers, - status_code=event.status_code, - ) - ) - else: - await self._send_h11_event( - h11.InformationalResponse( - headers=list(chain(event.headers, self.config.response_headers("h11"))), - status_code=event.status_code, - ) - ) - elif isinstance(event, InformationalResponse): - pass # Ignore for HTTP/1 - elif isinstance(event, Body): - await self._send_h11_event(h11.Data(data=event.data)) - elif isinstance(event, EndBody): - await self._send_h11_event(h11.EndOfMessage()) - elif isinstance(event, Data): - await self.send(RawData(data=event.data)) - elif isinstance(event, EndData): - pass - elif isinstance(event, StreamClosed): - await self._maybe_recycle() - - async def _handle_events(self) -> None: - while True: - if self.connection.they_are_waiting_for_100_continue: - await self._send_h11_event( - h11.InformationalResponse( - status_code=100, headers=self.config.response_headers("h11") - ) - ) - - try: - event = self.connection.next_event() - except h11.RemoteProtocolError as error: - if self.connection.our_state in {h11.IDLE, h11.SEND_RESPONSE}: - await self._send_error_response(error.error_status_hint) - await self.send(Closed()) - break - else: - if isinstance(event, h11.Request): - await self.send(Updated(idle=False)) - await self._check_protocol(event) - await self._create_stream(event) - elif event is h11.PAUSED: - await self.can_read.clear() - await self.can_read.wait() - elif isinstance(event, h11.ConnectionClosed) or event is h11.NEED_DATA: - break - elif self.stream is None: - break - elif isinstance(event, h11.Data): - await self.stream.handle(Body(stream_id=STREAM_ID, data=event.data)) - elif isinstance(event, h11.EndOfMessage): - await self.stream.handle(EndBody(stream_id=STREAM_ID)) - elif isinstance(event, Data): - # WebSocket pass through - await self.stream.handle(event) - - async def _create_stream(self, request: h11.Request) -> None: - upgrade_value = "" - connection_value = "" - for name, value in request.headers: - sanitised_name = name.decode("latin1").strip().lower() - if sanitised_name == "upgrade": - upgrade_value = value.decode("latin1").strip() - elif sanitised_name == "connection": - connection_value = value.decode("latin1").strip() - - connection_tokens = connection_value.lower().split(",") - if ( - any(token.strip() == "upgrade" for token in connection_tokens) - and upgrade_value.lower() == "websocket" - and request.method.decode("ascii").upper() == "GET" - ): - self.stream = WSStream( - self.app, - self.config, - self.context, - self.task_group, - self.ssl, - self.client, - self.server, - self.stream_send, - STREAM_ID, - ) - self.connection = H11WSConnection(cast(h11.Connection, self.connection)) - else: - self.stream = HTTPStream( - self.app, - self.config, - self.context, - self.task_group, - self.ssl, - self.client, - self.server, - self.stream_send, - STREAM_ID, - ) - - if self.config.h11_pass_raw_headers: - headers = request.headers.raw_items() - else: - headers = list(request.headers) - - await self.stream.handle( - Request( - stream_id=STREAM_ID, - headers=headers, - http_version=request.http_version.decode(), - method=request.method.decode("ascii").upper(), - raw_path=request.target, - state=self.connection_state, - ) - ) - self.keep_alive_requests += 1 - await self.context.mark_request() - - async def _send_h11_event(self, event: H11SendableEvent) -> None: - try: - data = self.connection.send(event) - except h11.LocalProtocolError: - if self.connection.their_state != h11.ERROR: - raise - else: - await self.send(RawData(data=data)) - - async def _send_error_response(self, status_code: int) -> None: - await self._send_h11_event( - h11.Response( - status_code=status_code, - headers=list( - chain( - [(b"content-length", b"0"), (b"connection", b"close")], - self.config.response_headers("h11"), - ) - ), - ) - ) - await self._send_h11_event(h11.EndOfMessage()) - - async def _maybe_recycle(self) -> None: - await self._close_stream() - if ( - not self.context.terminated.is_set() - and self.connection.our_state is h11.DONE - and self.connection.their_state is h11.DONE - ): - try: - self.connection.start_next_cycle() - except h11.LocalProtocolError: - await self.send(Closed()) - else: - self.response = None - self.scope = None - await self.can_read.set() - await self.send(Updated(idle=True)) - else: - await self.can_read.set() - await self.send(Closed()) - - async def _close_stream(self) -> None: - if self.stream is not None: - await self.stream.handle(StreamClosed(stream_id=STREAM_ID)) - self.stream = None - - async def _check_protocol(self, event: h11.Request) -> None: - upgrade_value = "" - has_body = False - for name, value in event.headers: - sanitised_name = name.decode("latin1").strip().lower() - if sanitised_name == "upgrade": - upgrade_value = value.decode("latin1").strip() - elif sanitised_name in {"content-length", "transfer-encoding"}: - has_body = True - - # h2c Upgrade requests with a body are a pain as the body must - # be fully recieved in HTTP/1.1 before the upgrade response - # and HTTP/2 takes over, so Hypercorn ignores the upgrade and - # responds in HTTP/1.1. Use a preflight OPTIONS request to - # initiate the upgrade if really required (or just use h2). - if upgrade_value.lower() == "h2c" and not has_body: - await self._send_h11_event( - h11.InformationalResponse( - status_code=101, - headers=self.config.response_headers("h11") - + [(b"connection", b"upgrade"), (b"upgrade", b"h2c")], - ) - ) - raise H2CProtocolRequiredError(self.connection.trailing_data[0], event) - elif event.method == b"PRI" and event.target == b"*" and event.http_version == b"2.0": - raise H2ProtocolAssumedError( - b"PRI * HTTP/2.0\r\n\r\n" + self.connection.trailing_data[0] - ) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h2.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h2.py deleted file mode 100644 index b19a2bc..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h2.py +++ /dev/null @@ -1,401 +0,0 @@ -from __future__ import annotations - -from typing import Awaitable, Callable, Dict, List, Optional, Tuple, Type, Union - -import h2 -import h2.connection -import h2.events -import h2.exceptions -import priority - -from .events import ( - Body, - Data, - EndBody, - EndData, - Event as StreamEvent, - InformationalResponse, - Request, - Response, - StreamClosed, - Trailers, -) -from .http_stream import HTTPStream -from .ws_stream import WSStream -from ..config import Config -from ..events import Closed, Event, RawData, Updated -from ..typing import AppWrapper, ConnectionState, Event as IOEvent, TaskGroup, WorkerContext -from ..utils import filter_pseudo_headers - -BUFFER_HIGH_WATER = 2 * 2**14 # Twice the default max frame size (two frames worth) -BUFFER_LOW_WATER = BUFFER_HIGH_WATER / 2 - - -class BufferCompleteError(Exception): - pass - - -class StreamBuffer: - def __init__(self, event_class: Type[IOEvent]) -> None: - self.buffer = bytearray() - self._complete = False - self._is_empty = event_class() - self._paused = event_class() - - async def drain(self) -> None: - await self._is_empty.wait() - - def set_complete(self) -> None: - self._complete = True - - async def close(self) -> None: - self._complete = True - self.buffer = bytearray() - await self._is_empty.set() - await self._paused.set() - - @property - def complete(self) -> bool: - return self._complete and len(self.buffer) == 0 - - async def push(self, data: bytes) -> None: - if self._complete: - raise BufferCompleteError() - self.buffer.extend(data) - await self._is_empty.clear() - if len(self.buffer) >= BUFFER_HIGH_WATER: - await self._paused.wait() - await self._paused.clear() - - async def pop(self, max_length: int) -> bytes: - length = min(len(self.buffer), max_length) - data = bytes(self.buffer[:length]) - del self.buffer[:length] - if len(data) < BUFFER_LOW_WATER: - await self._paused.set() - if len(self.buffer) == 0: - await self._is_empty.set() - return data - - -class H2Protocol: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - task_group: TaskGroup, - connection_state: ConnectionState, - ssl: bool, - client: Optional[Tuple[str, int]], - server: Optional[Tuple[str, int]], - send: Callable[[Event], Awaitable[None]], - ) -> None: - self.app = app - self.client = client - self.closed = False - self.config = config - self.context = context - self.task_group = task_group - self.connection_state = connection_state - - self.connection = h2.connection.H2Connection( - config=h2.config.H2Configuration(client_side=False, header_encoding=None) - ) - self.connection.DEFAULT_MAX_INBOUND_FRAME_SIZE = config.h2_max_inbound_frame_size - self.connection.local_settings = h2.settings.Settings( - client=False, - initial_values={ - h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: config.h2_max_concurrent_streams, - h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE: config.h2_max_header_list_size, - h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL: 1, - }, - ) - - self.keep_alive_requests = 0 - self.send = send - self.server = server - self.ssl = ssl - self.streams: Dict[int, Union[HTTPStream, WSStream]] = {} - # The below are used by the sending task - self.has_data = self.context.event_class() - self.priority = priority.PriorityTree() - self.stream_buffers: Dict[int, StreamBuffer] = {} - - @property - def idle(self) -> bool: - return len(self.streams) == 0 or all(stream.idle for stream in self.streams.values()) - - async def initiate( - self, headers: Optional[List[Tuple[bytes, bytes]]] = None, settings: Optional[str] = None - ) -> None: - if settings is not None: - self.connection.initiate_upgrade_connection(settings) - else: - self.connection.initiate_connection() - await self._flush() - if headers is not None: - event = h2.events.RequestReceived() - event.stream_id = 1 - event.headers = headers - await self._create_stream(event) - await self.streams[event.stream_id].handle(EndBody(stream_id=event.stream_id)) - self.task_group.spawn(self.send_task) - - async def send_task(self) -> None: - # This should be run in a seperate task to the rest of this - # class. This allows it seperately choose when to send, - # crucially in what order. - while not self.closed: - try: - stream_id = next(self.priority) - except priority.DeadlockError: - await self.has_data.wait() - await self.has_data.clear() - else: - await self._send_data(stream_id) - - async def _send_data(self, stream_id: int) -> None: - try: - chunk_size = min( - self.connection.local_flow_control_window(stream_id), - self.connection.max_outbound_frame_size, - ) - chunk_size = max(0, chunk_size) - data = await self.stream_buffers[stream_id].pop(chunk_size) - if data: - self.connection.send_data(stream_id, data) - await self._flush() - else: - self.priority.block(stream_id) - - if self.stream_buffers[stream_id].complete: - self.connection.end_stream(stream_id) - await self._flush() - del self.stream_buffers[stream_id] - self.priority.remove_stream(stream_id) - except (h2.exceptions.StreamClosedError, KeyError, h2.exceptions.ProtocolError): - # Stream or connection has closed whilst waiting to send - # data, not a problem - just force close it. - await self.stream_buffers[stream_id].close() - del self.stream_buffers[stream_id] - self.priority.remove_stream(stream_id) - - async def handle(self, event: Event) -> None: - if isinstance(event, RawData): - try: - events = self.connection.receive_data(event.data) - except h2.exceptions.ProtocolError: - await self._flush() - await self.send(Closed()) - else: - await self._handle_events(events) - elif isinstance(event, Closed): - self.closed = True - stream_ids = list(self.streams.keys()) - for stream_id in stream_ids: - await self._close_stream(stream_id) - await self.has_data.set() - - async def stream_send(self, event: StreamEvent) -> None: - try: - if isinstance(event, (InformationalResponse, Response)): - self.connection.send_headers( - event.stream_id, - [(b":status", b"%d" % event.status_code)] - + event.headers - + self.config.response_headers("h2"), - ) - await self._flush() - elif isinstance(event, (Body, Data)): - self.priority.unblock(event.stream_id) - await self.has_data.set() - await self.stream_buffers[event.stream_id].push(event.data) - elif isinstance(event, (EndBody, EndData)): - self.stream_buffers[event.stream_id].set_complete() - self.priority.unblock(event.stream_id) - await self.has_data.set() - await self.stream_buffers[event.stream_id].drain() - elif isinstance(event, Trailers): - self.connection.send_headers(event.stream_id, event.headers) - await self._flush() - elif isinstance(event, StreamClosed): - await self._close_stream(event.stream_id) - idle = len(self.streams) == 0 or all( - stream.idle for stream in self.streams.values() - ) - if idle and self.context.terminated.is_set(): - self.connection.close_connection() - await self._flush() - await self.send(Updated(idle=idle)) - elif isinstance(event, Request): - await self._create_server_push(event.stream_id, event.raw_path, event.headers) - except ( - BufferCompleteError, - KeyError, - priority.MissingStreamError, - h2.exceptions.ProtocolError, - ): - # Connection has closed whilst blocked on flow control or - # connection has advanced ahead of the last emitted event. - return - - async def _handle_events(self, events: List[h2.events.Event]) -> None: - for event in events: - if isinstance(event, h2.events.RequestReceived): - if self.context.terminated.is_set(): - self.connection.reset_stream(event.stream_id) - self.connection.update_settings( - {h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: 0} - ) - else: - await self._create_stream(event) - await self.send(Updated(idle=False)) - - if self.keep_alive_requests > self.config.keep_alive_max_requests: - self.connection.close_connection() - elif isinstance(event, h2.events.DataReceived): - await self.streams[event.stream_id].handle( - Body(stream_id=event.stream_id, data=event.data) - ) - self.connection.acknowledge_received_data( - event.flow_controlled_length, event.stream_id - ) - elif isinstance(event, h2.events.StreamEnded): - try: - await self.streams[event.stream_id].handle(EndBody(stream_id=event.stream_id)) - except KeyError: - # Response sent before full request received, - # nothing to do already closed. - pass - elif isinstance(event, h2.events.StreamReset): - await self._close_stream(event.stream_id) - await self._window_updated(event.stream_id) - elif isinstance(event, h2.events.WindowUpdated): - await self._window_updated(event.stream_id) - elif isinstance(event, h2.events.PriorityUpdated): - await self._priority_updated(event) - elif isinstance(event, h2.events.RemoteSettingsChanged): - if h2.settings.SettingCodes.INITIAL_WINDOW_SIZE in event.changed_settings: - await self._window_updated(None) - elif isinstance(event, h2.events.ConnectionTerminated): - await self.send(Closed()) - await self._flush() - - async def _flush(self) -> None: - data = self.connection.data_to_send() - if data != b"": - await self.send(RawData(data=data)) - - async def _window_updated(self, stream_id: Optional[int]) -> None: - if stream_id is None or stream_id == 0: - # Unblock all streams - for stream_id in list(self.stream_buffers.keys()): - self.priority.unblock(stream_id) - elif stream_id is not None and stream_id in self.stream_buffers: - self.priority.unblock(stream_id) - await self.has_data.set() - - async def _priority_updated(self, event: h2.events.PriorityUpdated) -> None: - try: - self.priority.reprioritize( - stream_id=event.stream_id, - depends_on=event.depends_on or None, - weight=event.weight, - exclusive=event.exclusive, - ) - except priority.MissingStreamError: - # Received PRIORITY frame before HEADERS frame - self.priority.insert_stream( - stream_id=event.stream_id, - depends_on=event.depends_on or None, - weight=event.weight, - exclusive=event.exclusive, - ) - self.priority.block(event.stream_id) - await self.has_data.set() - - async def _create_stream(self, request: h2.events.RequestReceived) -> None: - for name, value in request.headers: - if name == b":method": - method = value.decode("ascii").upper() - elif name == b":path": - raw_path = value - - if method == "CONNECT": - self.streams[request.stream_id] = WSStream( - self.app, - self.config, - self.context, - self.task_group, - self.ssl, - self.client, - self.server, - self.stream_send, - request.stream_id, - ) - else: - self.streams[request.stream_id] = HTTPStream( - self.app, - self.config, - self.context, - self.task_group, - self.ssl, - self.client, - self.server, - self.stream_send, - request.stream_id, - ) - self.stream_buffers[request.stream_id] = StreamBuffer(self.context.event_class) - try: - self.priority.insert_stream(request.stream_id) - except priority.DuplicateStreamError: - # Recieved PRIORITY frame before HEADERS frame - pass - else: - self.priority.block(request.stream_id) - - await self.streams[request.stream_id].handle( - Request( - stream_id=request.stream_id, - headers=filter_pseudo_headers(request.headers), - http_version="2", - method=method, - raw_path=raw_path, - state=self.connection_state, - ) - ) - self.keep_alive_requests += 1 - await self.context.mark_request() - - async def _create_server_push( - self, stream_id: int, path: bytes, headers: List[Tuple[bytes, bytes]] - ) -> None: - push_stream_id = self.connection.get_next_available_stream_id() - request_headers = [(b":method", b"GET"), (b":path", path)] - request_headers.extend(headers) - request_headers.extend(self.config.response_headers("h2")) - try: - self.connection.push_stream( - stream_id=stream_id, - promised_stream_id=push_stream_id, - request_headers=request_headers, - ) - await self._flush() - except h2.exceptions.ProtocolError: - # Client does not accept push promises or we are trying to - # push on a push promises request. - pass - else: - event = h2.events.RequestReceived() - event.stream_id = push_stream_id - event.headers = request_headers - await self._create_stream(event) - await self.streams[event.stream_id].handle(EndBody(stream_id=event.stream_id)) - self.keep_alive_requests += 1 - - async def _close_stream(self, stream_id: int) -> None: - if stream_id in self.streams: - stream = self.streams.pop(stream_id) - await stream.handle(StreamClosed(stream_id=stream_id)) - await self.has_data.set() diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h3.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h3.py deleted file mode 100644 index ae2eb8f..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/h3.py +++ /dev/null @@ -1,156 +0,0 @@ -from __future__ import annotations - -from typing import Awaitable, Callable, Dict, List, Optional, Tuple, Union - -from aioquic.h3.connection import H3Connection -from aioquic.h3.events import DataReceived, HeadersReceived -from aioquic.h3.exceptions import NoAvailablePushIDError -from aioquic.quic.connection import QuicConnection -from aioquic.quic.events import QuicEvent - -from .events import ( - Body, - Data, - EndBody, - EndData, - Event as StreamEvent, - InformationalResponse, - Request, - Response, - StreamClosed, - Trailers, -) -from .http_stream import HTTPStream -from .ws_stream import WSStream -from ..config import Config -from ..typing import AppWrapper, ConnectionState, TaskGroup, WorkerContext -from ..utils import filter_pseudo_headers - - -class H3Protocol: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - task_group: TaskGroup, - state: ConnectionState, - client: Optional[Tuple[str, int]], - server: Optional[Tuple[str, int]], - quic: QuicConnection, - send: Callable[[], Awaitable[None]], - ) -> None: - self.app = app - self.client = client - self.config = config - self.context = context - self.connection = H3Connection(quic) - self.send = send - self.server = server - self.streams: Dict[int, Union[HTTPStream, WSStream]] = {} - self.task_group = task_group - self.state = state - - async def handle(self, quic_event: QuicEvent) -> None: - for event in self.connection.handle_event(quic_event): - if isinstance(event, HeadersReceived): - if not self.context.terminated.is_set(): - await self._create_stream(event) - if event.stream_ended: - await self.streams[event.stream_id].handle( - EndBody(stream_id=event.stream_id) - ) - elif isinstance(event, DataReceived): - await self.streams[event.stream_id].handle( - Body(stream_id=event.stream_id, data=event.data) - ) - if event.stream_ended: - await self.streams[event.stream_id].handle(EndBody(stream_id=event.stream_id)) - - async def stream_send(self, event: StreamEvent) -> None: - if isinstance(event, (InformationalResponse, Response)): - self.connection.send_headers( - event.stream_id, - [(b":status", b"%d" % event.status_code)] - + event.headers - + self.config.response_headers("h3"), - ) - await self.send() - elif isinstance(event, (Body, Data)): - self.connection.send_data(event.stream_id, event.data, False) - await self.send() - elif isinstance(event, (EndBody, EndData)): - self.connection.send_data(event.stream_id, b"", True) - await self.send() - elif isinstance(event, Trailers): - self.connection.send_headers(event.stream_id, event.headers) - await self.send() - elif isinstance(event, StreamClosed): - pass # ?? - elif isinstance(event, Request): - await self._create_server_push(event.stream_id, event.raw_path, event.headers) - - async def _create_stream(self, request: HeadersReceived) -> None: - for name, value in request.headers: - if name == b":method": - method = value.decode("ascii").upper() - elif name == b":path": - raw_path = value - - if method == "CONNECT": - self.streams[request.stream_id] = WSStream( - self.app, - self.config, - self.context, - self.task_group, - True, - self.client, - self.server, - self.stream_send, - request.stream_id, - ) - else: - self.streams[request.stream_id] = HTTPStream( - self.app, - self.config, - self.context, - self.task_group, - True, - self.client, - self.server, - self.stream_send, - request.stream_id, - ) - - await self.streams[request.stream_id].handle( - Request( - stream_id=request.stream_id, - headers=filter_pseudo_headers(request.headers), - http_version="3", - method=method, - raw_path=raw_path, - state=self.state, - ) - ) - await self.context.mark_request() - - async def _create_server_push( - self, stream_id: int, path: bytes, headers: List[Tuple[bytes, bytes]] - ) -> None: - request_headers = [(b":method", b"GET"), (b":path", path)] - request_headers.extend(headers) - request_headers.extend(self.config.response_headers("h3")) - try: - push_stream_id = self.connection.send_push_promise( - stream_id=stream_id, headers=request_headers - ) - except NoAvailablePushIDError: - # Client does not accept push promises or we are trying to - # push on a push promises request. - pass - else: - event = HeadersReceived( - stream_id=push_stream_id, stream_ended=True, headers=request_headers - ) - await self._create_stream(event) - await self.streams[event.stream_id].handle(EndBody(stream_id=event.stream_id)) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/http_stream.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/http_stream.py deleted file mode 100644 index 7ffac1d..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/http_stream.py +++ /dev/null @@ -1,261 +0,0 @@ -from __future__ import annotations - -from enum import auto, Enum -from time import time -from typing import Awaitable, Callable, Optional, Tuple -from urllib.parse import unquote - -from .events import ( - Body, - EndBody, - Event, - InformationalResponse, - Request, - Response, - StreamClosed, - Trailers, -) -from ..config import Config -from ..typing import ( - AppWrapper, - ASGISendEvent, - HTTPResponseStartEvent, - HTTPScope, - TaskGroup, - WorkerContext, -) -from ..utils import ( - build_and_validate_headers, - suppress_body, - UnexpectedMessageError, - valid_server_name, -) - -TRAILERS_VERSIONS = {"2", "3"} -PUSH_VERSIONS = {"2", "3"} -EARLY_HINTS_VERSIONS = {"2", "3"} - - -class ASGIHTTPState(Enum): - # The ASGI Spec is clear that a response should not start till the - # framework has sent at least one body message hence why this - # state tracking is required. - REQUEST = auto() - RESPONSE = auto() - TRAILERS = auto() - CLOSED = auto() - - -class HTTPStream: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - task_group: TaskGroup, - ssl: bool, - client: Optional[Tuple[str, int]], - server: Optional[Tuple[str, int]], - send: Callable[[Event], Awaitable[None]], - stream_id: int, - ) -> None: - self.app = app - self.client = client - self.closed = False - self.config = config - self.context = context - self.response: HTTPResponseStartEvent - self.scope: HTTPScope - self.send = send - self.scheme = "https" if ssl else "http" - self.server = server - self.start_time: float - self.state = ASGIHTTPState.REQUEST - self.stream_id = stream_id - self.task_group = task_group - - @property - def idle(self) -> bool: - return False - - async def handle(self, event: Event) -> None: - if self.closed: - return - elif isinstance(event, Request): - self.start_time = time() - path, _, query_string = event.raw_path.partition(b"?") - self.scope = { - "type": "http", - "http_version": event.http_version, - "asgi": {"spec_version": "2.1", "version": "3.0"}, - "method": event.method, - "scheme": self.scheme, - "path": unquote(path.decode("ascii")), - "raw_path": path, - "query_string": query_string, - "root_path": self.config.root_path, - "headers": event.headers, - "client": self.client, - "server": self.server, - "state": event.state, - "extensions": {}, - } - - if event.http_version in TRAILERS_VERSIONS: - self.scope["extensions"]["http.response.trailers"] = {} - - if event.http_version in PUSH_VERSIONS: - self.scope["extensions"]["http.response.push"] = {} - - if event.http_version in EARLY_HINTS_VERSIONS: - self.scope["extensions"]["http.response.early_hint"] = {} - - if valid_server_name(self.config, event): - self.app_put = await self.task_group.spawn_app( - self.app, self.config, self.scope, self.app_send - ) - else: - await self._send_error_response(404) - self.closed = True - - elif isinstance(event, Body): - await self.app_put( - {"type": "http.request", "body": bytes(event.data), "more_body": True} - ) - elif isinstance(event, EndBody): - await self.app_put({"type": "http.request", "body": b"", "more_body": False}) - elif isinstance(event, StreamClosed): - self.closed = True - if self.state != ASGIHTTPState.CLOSED: - await self.config.log.access(self.scope, None, time() - self.start_time) - if self.app_put is not None: - await self.app_put({"type": "http.disconnect"}) - - async def app_send(self, message: Optional[ASGISendEvent]) -> None: - if message is None: # ASGI App has finished sending messages - if not self.closed: - # Cleanup if required - if self.state == ASGIHTTPState.REQUEST: - await self._send_error_response(500) - await self.send(StreamClosed(stream_id=self.stream_id)) - else: - if message["type"] == "http.response.start" and self.state == ASGIHTTPState.REQUEST: - self.response = message - headers = build_and_validate_headers(self.response.get("headers", [])) - await self.send( - Response( - stream_id=self.stream_id, - headers=headers, - status_code=int(self.response["status"]), - ) - ) - self.state = ASGIHTTPState.RESPONSE - elif ( - message["type"] == "http.response.push" - and self.scope["http_version"] in PUSH_VERSIONS - ): - if not isinstance(message["path"], str): - raise TypeError(f"{message['path']} should be a str") - headers = [(b":scheme", self.scope["scheme"].encode())] - for name, value in self.scope["headers"]: - if name == b"host": - headers.append((b":authority", value)) - headers.extend(build_and_validate_headers(message["headers"])) - await self.send( - Request( - stream_id=self.stream_id, - headers=headers, - http_version=self.scope["http_version"], - method="GET", - raw_path=message["path"].encode(), - state=self.scope["state"], - ) - ) - elif ( - message["type"] == "http.response.early_hint" - and self.scope["http_version"] in EARLY_HINTS_VERSIONS - and self.state == ASGIHTTPState.REQUEST - ): - headers = [(b"link", bytes(link).strip()) for link in message["links"]] - await self.send( - InformationalResponse( - stream_id=self.stream_id, - headers=headers, - status_code=103, - ) - ) - elif message["type"] == "http.response.body" and self.state == ASGIHTTPState.RESPONSE: - if ( - not suppress_body(self.scope["method"], int(self.response["status"])) - and message.get("body", b"") != b"" - ): - await self.send( - Body(stream_id=self.stream_id, data=bytes(message.get("body", b""))) - ) - - if not message.get("more_body", False): - if self.response.get("trailers", False): - self.state = ASGIHTTPState.TRAILERS - else: - await self._send_closed() - elif ( - message["type"] == "http.response.trailers" - and self.scope["http_version"] in TRAILERS_VERSIONS - and self.state == ASGIHTTPState.REQUEST - ): - for name, value in self.scope["headers"]: - if name == b"te" and value == b"trailers": - headers = build_and_validate_headers(message["headers"]) - self.response = { - "type": "http.response.start", - "status": 200, - "headers": headers, - } - await self.send( - Response( - stream_id=self.stream_id, - headers=headers, - status_code=200, - ) - ) - self.state = ASGIHTTPState.TRAILERS - break - - if not message.get("more_trailers", False): - await self._send_closed() - - elif ( - message["type"] == "http.response.trailers" - and self.scope["http_version"] in TRAILERS_VERSIONS - and self.state == ASGIHTTPState.TRAILERS - ): - for name, value in self.scope["headers"]: - if name == b"te" and value == b"trailers": - headers = build_and_validate_headers(message["headers"]) - await self.send(Trailers(stream_id=self.stream_id, headers=headers)) - break - - if not message.get("more_trailers", False): - await self._send_closed() - else: - raise UnexpectedMessageError(self.state, message["type"]) - - async def _send_closed(self) -> None: - await self.send(EndBody(stream_id=self.stream_id)) - self.state = ASGIHTTPState.CLOSED - await self.config.log.access(self.scope, self.response, time() - self.start_time) - await self.send(StreamClosed(stream_id=self.stream_id)) - - async def _send_error_response(self, status_code: int) -> None: - await self.send( - Response( - stream_id=self.stream_id, - headers=[(b"content-length", b"0"), (b"connection", b"close")], - status_code=status_code, - ) - ) - await self.send(EndBody(stream_id=self.stream_id)) - self.state = ASGIHTTPState.CLOSED - await self.config.log.access( - self.scope, {"status": status_code, "headers": []}, time() - self.start_time - ) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/quic.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/quic.py deleted file mode 100644 index 40625a6..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/quic.py +++ /dev/null @@ -1,157 +0,0 @@ -from __future__ import annotations - -from dataclasses import dataclass -from functools import partial -from typing import Awaitable, Callable, Dict, Optional, Set, Tuple - -from aioquic.buffer import Buffer -from aioquic.h3.connection import H3_ALPN -from aioquic.quic.configuration import QuicConfiguration -from aioquic.quic.connection import QuicConnection -from aioquic.quic.events import ( - ConnectionIdIssued, - ConnectionIdRetired, - ConnectionTerminated, - ProtocolNegotiated, -) -from aioquic.quic.packet import ( - encode_quic_version_negotiation, - PACKET_TYPE_INITIAL, - pull_quic_header, -) - -from .h3 import H3Protocol -from ..config import Config -from ..events import Closed, Event, RawData -from ..typing import AppWrapper, ConnectionState, SingleTask, TaskGroup, WorkerContext - - -@dataclass -class _Connection: - cids: Set[bytes] - quic: QuicConnection - task: SingleTask - h3: Optional[H3Protocol] = None - - -class QuicProtocol: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - task_group: TaskGroup, - state: ConnectionState, - server: Optional[Tuple[str, int]], - send: Callable[[Event], Awaitable[None]], - ) -> None: - self.app = app - self.config = config - self.context = context - self.connections: Dict[bytes, _Connection] = {} - self.send = send - self.server = server - self.task_group = task_group - self.state = state - - self.quic_config = QuicConfiguration(alpn_protocols=H3_ALPN, is_client=False) - self.quic_config.load_cert_chain(certfile=config.certfile, keyfile=config.keyfile) - - @property - def idle(self) -> bool: - return len(self.connections) == 0 - - async def handle(self, event: Event) -> None: - if isinstance(event, RawData): - try: - header = pull_quic_header(Buffer(data=event.data), host_cid_length=8) - except ValueError: - return - if ( - header.version is not None - and header.version not in self.quic_config.supported_versions - ): - data = encode_quic_version_negotiation( - source_cid=header.destination_cid, - destination_cid=header.source_cid, - supported_versions=self.quic_config.supported_versions, - ) - await self.send(RawData(data=data, address=event.address)) - return - - connection = self.connections.get(header.destination_cid) - if ( - connection is None - and len(event.data) >= 1200 - and header.packet_type == PACKET_TYPE_INITIAL - and not self.context.terminated.is_set() - ): - quic_connection = QuicConnection( - configuration=self.quic_config, - original_destination_connection_id=header.destination_cid, - ) - connection = _Connection( - cids={header.destination_cid, quic_connection.host_cid}, - quic=quic_connection, - task=self.context.single_task_class(), - ) - self.connections[header.destination_cid] = connection - self.connections[quic_connection.host_cid] = connection - - if connection is not None: - connection.quic.receive_datagram(event.data, event.address, now=self.context.time()) - await self._handle_events(connection, event.address) - elif isinstance(event, Closed): - pass - - async def send_all(self, connection: _Connection) -> None: - for data, address in connection.quic.datagrams_to_send(now=self.context.time()): - await self.send(RawData(data=data, address=address)) - - timer = connection.quic.get_timer() - if timer is not None: - await connection.task.restart( - self.task_group, partial(self._handle_timer, timer, connection) - ) - - async def _handle_events( - self, connection: _Connection, client: Optional[Tuple[str, int]] = None - ) -> None: - event = connection.quic.next_event() - while event is not None: - if isinstance(event, ConnectionTerminated): - await connection.task.stop() - for cid in connection.cids: - del self.connections[cid] - connection.cids = set() - elif isinstance(event, ProtocolNegotiated): - connection.h3 = H3Protocol( - self.app, - self.config, - self.context, - self.task_group, - self.state, - client, - self.server, - connection.quic, - partial(self.send_all, connection), - ) - elif isinstance(event, ConnectionIdIssued): - connection.cids.add(event.connection_id) - self.connections[event.connection_id] = connection - elif isinstance(event, ConnectionIdRetired): - connection.cids.remove(event.connection_id) - del self.connections[event.connection_id] - - if connection.h3 is not None: - await connection.h3.handle(event) - - event = connection.quic.next_event() - - await self.send_all(connection) - - async def _handle_timer(self, timer: float, connection: _Connection) -> None: - wait = max(0, timer - self.context.time()) - await self.context.sleep(wait) - connection.quic.handle_timer(now=self.context.time()) - await self._handle_events(connection, None) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/ws_stream.py b/serverenv/lib/python3.9/site-packages/hypercorn/protocol/ws_stream.py deleted file mode 100644 index 7b39815..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/protocol/ws_stream.py +++ /dev/null @@ -1,385 +0,0 @@ -from __future__ import annotations - -from enum import auto, Enum -from io import BytesIO, StringIO -from time import time -from typing import Awaitable, Callable, Iterable, List, Optional, Tuple, Union -from urllib.parse import unquote - -from wsproto.connection import Connection, ConnectionState, ConnectionType -from wsproto.events import ( - BytesMessage, - CloseConnection, - Event as WSProtoEvent, - Message, - Ping, - TextMessage, -) -from wsproto.extensions import Extension, PerMessageDeflate -from wsproto.frame_protocol import CloseReason -from wsproto.handshake import server_extensions_handshake, WEBSOCKET_VERSION -from wsproto.utilities import generate_accept_token, LocalProtocolError, split_comma_header - -from .events import Body, Data, EndBody, EndData, Event, Request, Response, StreamClosed -from ..config import Config -from ..typing import ( - AppWrapper, - ASGISendEvent, - TaskGroup, - WebsocketAcceptEvent, - WebsocketResponseBodyEvent, - WebsocketResponseStartEvent, - WebsocketScope, - WorkerContext, -) -from ..utils import ( - build_and_validate_headers, - suppress_body, - UnexpectedMessageError, - valid_server_name, -) - - -class ASGIWebsocketState(Enum): - # Hypercorn supports the ASGI websocket HTTP response extension, - # which allows HTTP responses rather than acceptance. - HANDSHAKE = auto() - CONNECTED = auto() - RESPONSE = auto() - CLOSED = auto() - HTTPCLOSED = auto() - - -class FrameTooLargeError(Exception): - pass - - -class Handshake: - def __init__(self, headers: List[Tuple[bytes, bytes]], http_version: str) -> None: - self.accepted = False - self.http_version = http_version - self.connection_tokens: Optional[List[str]] = None - self.extensions: Optional[List[str]] = None - self.key: Optional[bytes] = None - self.subprotocols: Optional[List[str]] = None - self.upgrade: Optional[bytes] = None - self.version: Optional[bytes] = None - for name, value in headers: - name = name.lower() - if name == b"connection": - self.connection_tokens = split_comma_header(value) - elif name == b"sec-websocket-extensions": - self.extensions = split_comma_header(value) - elif name == b"sec-websocket-key": - self.key = value - elif name == b"sec-websocket-protocol": - self.subprotocols = split_comma_header(value) - elif name == b"sec-websocket-version": - self.version = value - elif name == b"upgrade": - self.upgrade = value - - def is_valid(self) -> bool: - if self.http_version < "1.1": - return False - elif self.http_version == "1.1": - if self.key is None: - return False - if self.connection_tokens is None or not any( - token.lower() == "upgrade" for token in self.connection_tokens - ): - return False - if self.upgrade.lower() != b"websocket": - return False - - if self.version != WEBSOCKET_VERSION: - return False - return True - - def accept( - self, - subprotocol: Optional[str], - additional_headers: Iterable[Tuple[bytes, bytes]], - ) -> Tuple[int, List[Tuple[bytes, bytes]], Connection]: - headers = [] - if subprotocol is not None: - if self.subprotocols is None or subprotocol not in self.subprotocols: - raise Exception("Invalid Subprotocol") - else: - headers.append((b"sec-websocket-protocol", subprotocol.encode())) - - extensions: List[Extension] = [PerMessageDeflate()] - accepts = None - if self.extensions is not None: - accepts = server_extensions_handshake(self.extensions, extensions) - - if accepts: - headers.append((b"sec-websocket-extensions", accepts)) - - if self.key is not None: - headers.append((b"sec-websocket-accept", generate_accept_token(self.key))) - - status_code = 200 - if self.http_version == "1.1": - headers.extend([(b"upgrade", b"WebSocket"), (b"connection", b"Upgrade")]) - status_code = 101 - - for name, value in additional_headers: - if b"sec-websocket-protocol" == name or name.startswith(b":"): - raise Exception(f"Invalid additional header, {name.decode()}") - - headers.append((name, value)) - - self.accepted = True - return status_code, headers, Connection(ConnectionType.SERVER, extensions) - - -class WebsocketBuffer: - def __init__(self, max_length: int) -> None: - self.value: Optional[Union[BytesIO, StringIO]] = None - self.length = 0 - self.max_length = max_length - - def extend(self, event: Message) -> None: - if self.value is None: - if isinstance(event, TextMessage): - self.value = StringIO() - else: - self.value = BytesIO() - self.length += self.value.write(event.data) - if self.length > self.max_length: - raise FrameTooLargeError() - - def clear(self) -> None: - self.value = None - self.length = 0 - - def to_message(self) -> dict: - return { - "type": "websocket.receive", - "bytes": self.value.getvalue() if isinstance(self.value, BytesIO) else None, - "text": self.value.getvalue() if isinstance(self.value, StringIO) else None, - } - - -class WSStream: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - task_group: TaskGroup, - ssl: bool, - client: Optional[Tuple[str, int]], - server: Optional[Tuple[str, int]], - send: Callable[[Event], Awaitable[None]], - stream_id: int, - ) -> None: - self.app = app - self.app_put: Optional[Callable] = None - self.buffer = WebsocketBuffer(config.websocket_max_message_size) - self.client = client - self.closed = False - self.config = config - self.context = context - self.task_group = task_group - self.response: WebsocketResponseStartEvent - self.scope: WebsocketScope - self.send = send - # RFC 8441 for HTTP/2 says use http or https, ASGI says ws or wss - self.scheme = "wss" if ssl else "ws" - self.server = server - self.start_time: float - self.state = ASGIWebsocketState.HANDSHAKE - self.stream_id = stream_id - - self.connection: Connection - self.handshake: Handshake - - @property - def idle(self) -> bool: - return self.state in {ASGIWebsocketState.CLOSED, ASGIWebsocketState.HTTPCLOSED} - - async def handle(self, event: Event) -> None: - if self.closed: - return - elif isinstance(event, Request): - self.start_time = time() - self.handshake = Handshake(event.headers, event.http_version) - path, _, query_string = event.raw_path.partition(b"?") - self.scope = { - "type": "websocket", - "asgi": {"spec_version": "2.3", "version": "3.0"}, - "scheme": self.scheme, - "http_version": event.http_version, - "path": unquote(path.decode("ascii")), - "raw_path": path, - "query_string": query_string, - "root_path": self.config.root_path, - "headers": event.headers, - "client": self.client, - "server": self.server, - "state": event.state, - "subprotocols": self.handshake.subprotocols or [], - "extensions": {"websocket.http.response": {}}, - } - - if not valid_server_name(self.config, event): - await self._send_error_response(404) - self.closed = True - elif not self.handshake.is_valid(): - await self._send_error_response(400) - self.closed = True - else: - self.app_put = await self.task_group.spawn_app( - self.app, self.config, self.scope, self.app_send - ) - await self.app_put({"type": "websocket.connect"}) - elif isinstance(event, (Body, Data)) and not self.handshake.accepted: - await self._send_error_response(400) - self.closed = True - elif isinstance(event, (Body, Data)): - self.connection.receive_data(event.data) - await self._handle_events() - elif isinstance(event, StreamClosed): - self.closed = True - if self.app_put is not None: - if self.state in {ASGIWebsocketState.HTTPCLOSED, ASGIWebsocketState.CLOSED}: - code = CloseReason.NORMAL_CLOSURE.value - else: - code = CloseReason.ABNORMAL_CLOSURE.value - await self.app_put({"type": "websocket.disconnect", "code": code}) - - async def app_send(self, message: Optional[ASGISendEvent]) -> None: - if self.closed: - # Allow app to finish after close - return - - if message is None: # ASGI App has finished sending messages - # Cleanup if required - if self.state == ASGIWebsocketState.HANDSHAKE: - await self._send_error_response(500) - await self.config.log.access( - self.scope, {"status": 500, "headers": []}, time() - self.start_time - ) - elif self.state == ASGIWebsocketState.CONNECTED: - await self._send_wsproto_event(CloseConnection(code=CloseReason.INTERNAL_ERROR)) - await self.send(StreamClosed(stream_id=self.stream_id)) - else: - if message["type"] == "websocket.accept" and self.state == ASGIWebsocketState.HANDSHAKE: - await self._accept(message) - elif ( - message["type"] == "websocket.http.response.start" - and self.state == ASGIWebsocketState.HANDSHAKE - ): - self.response = message - elif message["type"] == "websocket.http.response.body" and self.state in { - ASGIWebsocketState.HANDSHAKE, - ASGIWebsocketState.RESPONSE, - }: - await self._send_rejection(message) - elif message["type"] == "websocket.send" and self.state == ASGIWebsocketState.CONNECTED: - event: WSProtoEvent - if message.get("bytes") is not None: - event = BytesMessage(data=bytes(message["bytes"])) - elif not isinstance(message["text"], str): - raise TypeError(f"{message['text']} should be a str") - else: - event = TextMessage(data=message["text"]) - await self._send_wsproto_event(event) - elif ( - message["type"] == "websocket.close" and self.state == ASGIWebsocketState.HANDSHAKE - ): - self.state = ASGIWebsocketState.HTTPCLOSED - await self._send_error_response(403) - elif message["type"] == "websocket.close": - self.state = ASGIWebsocketState.CLOSED - await self._send_wsproto_event( - CloseConnection( - code=int(message.get("code", CloseReason.NORMAL_CLOSURE)), - reason=message.get("reason"), - ) - ) - await self.send(EndData(stream_id=self.stream_id)) - else: - raise UnexpectedMessageError(self.state, message["type"]) - - async def _handle_events(self) -> None: - for event in self.connection.events(): - if isinstance(event, Message): - try: - self.buffer.extend(event) - except FrameTooLargeError: - await self._send_wsproto_event( - CloseConnection(code=CloseReason.MESSAGE_TOO_BIG) - ) - break - - if event.message_finished: - await self.app_put(self.buffer.to_message()) - self.buffer.clear() - elif isinstance(event, Ping): - await self._send_wsproto_event(event.response()) - elif isinstance(event, CloseConnection): - if self.connection.state == ConnectionState.REMOTE_CLOSING: - await self._send_wsproto_event(event.response()) - await self.send(StreamClosed(stream_id=self.stream_id)) - - async def _send_error_response(self, status_code: int) -> None: - await self.send( - Response( - stream_id=self.stream_id, - status_code=status_code, - headers=[(b"content-length", b"0"), (b"connection", b"close")], - ) - ) - await self.send(EndBody(stream_id=self.stream_id)) - await self.config.log.access( - self.scope, {"status": status_code, "headers": []}, time() - self.start_time - ) - - async def _send_wsproto_event(self, event: WSProtoEvent) -> None: - try: - data = self.connection.send(event) - except LocalProtocolError: - pass - else: - await self.send(Data(stream_id=self.stream_id, data=data)) - - async def _accept(self, message: WebsocketAcceptEvent) -> None: - self.state = ASGIWebsocketState.CONNECTED - status_code, headers, self.connection = self.handshake.accept( - message.get("subprotocol"), message.get("headers", []) - ) - await self.send( - Response(stream_id=self.stream_id, status_code=status_code, headers=headers) - ) - await self.config.log.access( - self.scope, {"status": status_code, "headers": []}, time() - self.start_time - ) - if self.config.websocket_ping_interval is not None: - self.task_group.spawn(self._send_pings) - - async def _send_rejection(self, message: WebsocketResponseBodyEvent) -> None: - body_suppressed = suppress_body("GET", self.response["status"]) - if self.state == ASGIWebsocketState.HANDSHAKE: - headers = build_and_validate_headers(self.response["headers"]) - await self.send( - Response( - stream_id=self.stream_id, - status_code=int(self.response["status"]), - headers=headers, - ) - ) - self.state = ASGIWebsocketState.RESPONSE - if not body_suppressed: - await self.send(Body(stream_id=self.stream_id, data=bytes(message.get("body", b"")))) - if not message.get("more_body", False): - self.state = ASGIWebsocketState.HTTPCLOSED - await self.send(EndBody(stream_id=self.stream_id)) - await self.config.log.access(self.scope, self.response, time() - self.start_time) - - async def _send_pings(self) -> None: - while not self.closed: - await self._send_wsproto_event(Ping()) - await self.context.sleep(self.config.websocket_ping_interval) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/py.typed b/serverenv/lib/python3.9/site-packages/hypercorn/py.typed deleted file mode 100644 index f5642f7..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/py.typed +++ /dev/null @@ -1 +0,0 @@ -Marker diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/run.py b/serverenv/lib/python3.9/site-packages/hypercorn/run.py deleted file mode 100644 index cfe801a..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/run.py +++ /dev/null @@ -1,145 +0,0 @@ -from __future__ import annotations - -import platform -import signal -import time -from multiprocessing import get_context -from multiprocessing.connection import wait -from multiprocessing.context import BaseContext -from multiprocessing.process import BaseProcess -from multiprocessing.synchronize import Event as EventType -from pickle import PicklingError -from typing import Any, List - -from .config import Config, Sockets -from .typing import WorkerFunc -from .utils import check_for_updates, files_to_watch, load_application, write_pid_file - - -def run(config: Config) -> int: - if config.pid_path is not None: - write_pid_file(config.pid_path) - - worker_func: WorkerFunc - if config.worker_class == "asyncio": - from .asyncio.run import asyncio_worker - - worker_func = asyncio_worker - elif config.worker_class == "uvloop": - from .asyncio.run import uvloop_worker - - worker_func = uvloop_worker - elif config.worker_class == "trio": - from .trio.run import trio_worker - - worker_func = trio_worker - else: - raise ValueError(f"No worker of class {config.worker_class} exists") - - sockets = config.create_sockets() - - if config.use_reloader and config.workers == 0: - raise RuntimeError("Cannot reload without workers") - - exitcode = 0 - if config.workers == 0: - worker_func(config, sockets) - else: - if config.use_reloader: - # Load the application so that the correct paths are checked for - # changes, but only when the reloader is being used. - load_application(config.application_path, config.wsgi_max_body_size) - - ctx = get_context("spawn") - - active = True - shutdown_event = ctx.Event() - - def shutdown(*args: Any) -> None: - nonlocal active, shutdown_event - shutdown_event.set() - active = False - - processes: List[BaseProcess] = [] - while active: - # Ignore SIGINT before creating the processes, so that they - # inherit the signal handling. This means that the shutdown - # function controls the shutdown. - signal.signal(signal.SIGINT, signal.SIG_IGN) - - _populate(processes, config, worker_func, sockets, shutdown_event, ctx) - - for signal_name in {"SIGINT", "SIGTERM", "SIGBREAK"}: - if hasattr(signal, signal_name): - signal.signal(getattr(signal, signal_name), shutdown) - - if config.use_reloader: - files = files_to_watch() - while True: - finished = wait((process.sentinel for process in processes), timeout=1) - updated = check_for_updates(files) - if updated: - shutdown_event.set() - for process in processes: - process.join() - shutdown_event.clear() - break - if len(finished) > 0: - break - else: - wait(process.sentinel for process in processes) - - exitcode = _join_exited(processes) - if exitcode != 0: - shutdown_event.set() - active = False - - for process in processes: - process.terminate() - - exitcode = _join_exited(processes) if exitcode != 0 else exitcode - - for sock in sockets.secure_sockets: - sock.close() - - for sock in sockets.insecure_sockets: - sock.close() - - return exitcode - - -def _populate( - processes: List[BaseProcess], - config: Config, - worker_func: WorkerFunc, - sockets: Sockets, - shutdown_event: EventType, - ctx: BaseContext, -) -> None: - for _ in range(config.workers - len(processes)): - process = ctx.Process( # type: ignore - target=worker_func, - kwargs={"config": config, "shutdown_event": shutdown_event, "sockets": sockets}, - ) - process.daemon = True - try: - process.start() - except PicklingError as error: - raise RuntimeError( - "Cannot pickle the config, see https://docs.python.org/3/library/pickle.html#pickle-picklable" # noqa: E501 - ) from error - processes.append(process) - if platform.system() == "Windows": - time.sleep(0.1) - - -def _join_exited(processes: List[BaseProcess]) -> int: - exitcode = 0 - for index in reversed(range(len(processes))): - worker = processes[index] - if worker.exitcode is not None: - worker.join() - exitcode = worker.exitcode if exitcode == 0 else exitcode - del processes[index] - - return exitcode diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/statsd.py b/serverenv/lib/python3.9/site-packages/hypercorn/statsd.py deleted file mode 100644 index 58e2cde..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/statsd.py +++ /dev/null @@ -1,96 +0,0 @@ -from __future__ import annotations - -from typing import Any, Optional, TYPE_CHECKING - -from .logging import Logger - -if TYPE_CHECKING: - from .config import Config - from .typing import ResponseSummary, WWWScope - -METRIC_VAR = "metric" -VALUE_VAR = "value" -MTYPE_VAR = "mtype" -GAUGE_TYPE = "gauge" -COUNTER_TYPE = "counter" -HISTOGRAM_TYPE = "histogram" - - -class StatsdLogger(Logger): - def __init__(self, config: "Config") -> None: - super().__init__(config) - self.dogstatsd_tags = config.dogstatsd_tags - self.prefix = config.statsd_prefix - if len(self.prefix) and self.prefix[-1] != ".": - self.prefix += "." - - async def critical(self, message: str, *args: Any, **kwargs: Any) -> None: - await super().critical(message, *args, **kwargs) - await self.increment("hypercorn.log.critical", 1) - - async def error(self, message: str, *args: Any, **kwargs: Any) -> None: - await super().error(message, *args, **kwargs) - await self.increment("hypercorn.log.error", 1) - - async def warning(self, message: str, *args: Any, **kwargs: Any) -> None: - await super().warning(message, *args, **kwargs) - await self.increment("hypercorn.log.warning", 1) - - async def info(self, message: str, *args: Any, **kwargs: Any) -> None: - await super().info(message, *args, **kwargs) - - async def debug(self, message: str, *args: Any, **kwargs: Any) -> None: - await super().debug(message, *args, **kwargs) - - async def exception(self, message: str, *args: Any, **kwargs: Any) -> None: - await super().exception(message, *args, **kwargs) - await self.increment("hypercorn.log.exception", 1) - - async def log(self, level: int, message: str, *args: Any, **kwargs: Any) -> None: - try: - extra = kwargs.get("extra", None) - if extra is not None: - metric = extra.get(METRIC_VAR, None) - value = extra.get(VALUE_VAR, None) - type_ = extra.get(MTYPE_VAR, None) - if metric and value and type_: - if type_ == GAUGE_TYPE: - await self.gauge(metric, value) - elif type_ == COUNTER_TYPE: - await self.increment(metric, value) - elif type_ == HISTOGRAM_TYPE: - await self.histogram(metric, value) - - if message: - await super().log(level, message, *args, **kwargs) - except Exception: - await super().warning("Failed to log to statsd", exc_info=True) - - async def access( - self, request: "WWWScope", response: Optional["ResponseSummary"], request_time: float - ) -> None: - await super().access(request, response, request_time) - await self.histogram("hypercorn.request.duration", request_time * 1_000) - await self.increment("hypercorn.requests", 1) - if response is not None: - await self.increment(f"hypercorn.request.status.{response['status']}", 1) - - async def gauge(self, name: str, value: int) -> None: - await self._send(f"{self.prefix}{name}:{value}|g") - - async def increment(self, name: str, value: int, sampling_rate: float = 1.0) -> None: - await self._send(f"{self.prefix}{name}:{value}|c|@{sampling_rate}") - - async def decrement(self, name: str, value: int, sampling_rate: float = 1.0) -> None: - await self._send(f"{self.prefix}{name}:-{value}|c|@{sampling_rate}") - - async def histogram(self, name: str, value: float) -> None: - await self._send(f"{self.prefix}{name}:{value}|ms") - - async def _send(self, message: str) -> None: - if self.dogstatsd_tags: - message = f"{message}|#{self.dogstatsd_tags}" - await self._socket_send(message.encode("ascii")) - - async def _socket_send(self, message: bytes) -> None: - raise NotImplementedError() diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/__init__.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/__init__.py deleted file mode 100644 index 44a2eb9..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/__init__.py +++ /dev/null @@ -1,52 +0,0 @@ -from __future__ import annotations - -import warnings -from typing import Awaitable, Callable, Literal, Optional - -import trio - -from .run import worker_serve -from ..config import Config -from ..typing import Framework -from ..utils import wrap_app - - -async def serve( - app: Framework, - config: Config, - *, - shutdown_trigger: Optional[Callable[..., Awaitable[None]]] = None, - task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED, - mode: Optional[Literal["asgi", "wsgi"]] = None, -) -> None: - """Serve an ASGI framework app given the config. - - This allows for a programmatic way to serve an ASGI framework, it - can be used via, - - .. code-block:: python - - trio.run(serve, app, config) - - It is assumed that the event-loop is configured before calling - this function, therefore configuration values that relate to loop - setup or process setup are ignored. - - Arguments: - app: The ASGI application to serve. - config: A Hypercorn configuration object. - shutdown_trigger: This should return to trigger a graceful - shutdown. - mode: Specify if the app is WSGI or ASGI. - """ - if config.debug: - warnings.warn("The config `debug` has no affect when using serve", Warning) - if config.workers != 1: - warnings.warn("The config `workers` has no affect when using serve", Warning) - - await worker_serve( - wrap_app(app, config.wsgi_max_body_size, mode), - config, - shutdown_trigger=shutdown_trigger, - task_status=task_status, - ) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/lifespan.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/lifespan.py deleted file mode 100644 index cd80984..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/lifespan.py +++ /dev/null @@ -1,110 +0,0 @@ -from __future__ import annotations - -import sys - -import trio - -from ..config import Config -from ..typing import AppWrapper, ASGIReceiveEvent, ASGISendEvent, LifespanScope, LifespanState -from ..utils import LifespanFailureError, LifespanTimeoutError - -if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - - -class UnexpectedMessageError(Exception): - pass - - -class Lifespan: - def __init__(self, app: AppWrapper, config: Config, state: LifespanState) -> None: - self.app = app - self.config = config - self.startup = trio.Event() - self.shutdown = trio.Event() - self.app_send_channel, self.app_receive_channel = trio.open_memory_channel( - config.max_app_queue_size - ) - self.state = state - self.supported = True - - async def handle_lifespan( - self, *, task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED - ) -> None: - task_status.started() - scope: LifespanScope = { - "type": "lifespan", - "asgi": {"spec_version": "2.0", "version": "3.0"}, - "state": self.state, - } - try: - await self.app( - scope, - self.asgi_receive, - self.asgi_send, - trio.to_thread.run_sync, - trio.from_thread.run, - ) - except LifespanFailureError: - # Lifespan failures should crash the server - raise - except (BaseExceptionGroup, Exception) as error: - if isinstance(error, BaseExceptionGroup): - failure_error = error.subgroup(LifespanFailureError) - if failure_error is not None: - # Lifespan failures should crash the server - raise failure_error - - self.supported = False - if not self.startup.is_set(): - await self.config.log.warning( - "ASGI Framework Lifespan error, continuing without Lifespan support" - ) - elif not self.shutdown.is_set(): - await self.config.log.exception( - "ASGI Framework Lifespan error, shutdown without Lifespan support" - ) - else: - await self.config.log.exception("ASGI Framework Lifespan errored after shutdown.") - finally: - self.startup.set() - self.shutdown.set() - await self.app_send_channel.aclose() - await self.app_receive_channel.aclose() - - async def wait_for_startup(self) -> None: - if not self.supported: - return - - await self.app_send_channel.send({"type": "lifespan.startup"}) - try: - with trio.fail_after(self.config.startup_timeout): - await self.startup.wait() - except trio.TooSlowError as error: - raise LifespanTimeoutError("startup") from error - - async def wait_for_shutdown(self) -> None: - if not self.supported: - return - - await self.app_send_channel.send({"type": "lifespan.shutdown"}) - try: - with trio.fail_after(self.config.shutdown_timeout): - await self.shutdown.wait() - except trio.TooSlowError as error: - raise LifespanTimeoutError("startup") from error - - async def asgi_receive(self) -> ASGIReceiveEvent: - return await self.app_receive_channel.receive() - - async def asgi_send(self, message: ASGISendEvent) -> None: - if message["type"] == "lifespan.startup.complete": - self.startup.set() - elif message["type"] == "lifespan.shutdown.complete": - self.shutdown.set() - elif message["type"] == "lifespan.startup.failed": - raise LifespanFailureError("startup", message.get("message", "")) - elif message["type"] == "lifespan.shutdown.failed": - raise LifespanFailureError("shutdown", message.get("message", "")) - else: - raise UnexpectedMessageError(message["type"]) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/run.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/run.py deleted file mode 100644 index 0d25368..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/run.py +++ /dev/null @@ -1,138 +0,0 @@ -from __future__ import annotations - -import sys -from functools import partial -from multiprocessing.synchronize import Event as EventType -from random import randint -from typing import Awaitable, Callable, Optional - -import trio - -from .lifespan import Lifespan -from .statsd import StatsdLogger -from .tcp_server import TCPServer -from .udp_server import UDPServer -from .worker_context import WorkerContext -from ..config import Config, Sockets -from ..typing import AppWrapper, ConnectionState, LifespanState -from ..utils import ( - check_multiprocess_shutdown_event, - load_application, - raise_shutdown, - repr_socket_addr, - ShutdownError, -) - -if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - - -async def worker_serve( - app: AppWrapper, - config: Config, - *, - sockets: Optional[Sockets] = None, - shutdown_trigger: Optional[Callable[..., Awaitable[None]]] = None, - task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED, -) -> None: - config.set_statsd_logger_class(StatsdLogger) - - lifespan_state: LifespanState = {} - lifespan = Lifespan(app, config, lifespan_state) - max_requests = None - if config.max_requests is not None: - max_requests = config.max_requests + randint(0, config.max_requests_jitter) - context = WorkerContext(max_requests) - - async with trio.open_nursery() as lifespan_nursery: - await lifespan_nursery.start(lifespan.handle_lifespan) - await lifespan.wait_for_startup() - - async with trio.open_nursery() as server_nursery: - if sockets is None: - sockets = config.create_sockets() - for sock in sockets.secure_sockets: - sock.listen(config.backlog) - for sock in sockets.insecure_sockets: - sock.listen(config.backlog) - - ssl_context = config.create_ssl_context() - listeners = [] - binds = [] - for sock in sockets.secure_sockets: - listeners.append( - trio.SSLListener( - trio.SocketListener(trio.socket.from_stdlib_socket(sock)), - ssl_context, - https_compatible=True, - ) - ) - bind = repr_socket_addr(sock.family, sock.getsockname()) - binds.append(f"https://{bind}") - await config.log.info(f"Running on https://{bind} (CTRL + C to quit)") - - for sock in sockets.insecure_sockets: - listeners.append(trio.SocketListener(trio.socket.from_stdlib_socket(sock))) - bind = repr_socket_addr(sock.family, sock.getsockname()) - binds.append(f"http://{bind}") - await config.log.info(f"Running on http://{bind} (CTRL + C to quit)") - - for sock in sockets.quic_sockets: - await server_nursery.start( - UDPServer( - app, config, context, ConnectionState(lifespan_state.copy()), sock - ).run - ) - bind = repr_socket_addr(sock.family, sock.getsockname()) - await config.log.info(f"Running on https://{bind} (QUIC) (CTRL + C to quit)") - - task_status.started(binds) - try: - async with trio.open_nursery(strict_exception_groups=True) as nursery: - if shutdown_trigger is not None: - nursery.start_soon(raise_shutdown, shutdown_trigger) - nursery.start_soon(raise_shutdown, context.terminate.wait) - - nursery.start_soon( - partial( - trio.serve_listeners, - partial( - TCPServer, - app, - config, - context, - ConnectionState(lifespan_state.copy()), - ), - listeners, - handler_nursery=server_nursery, - ), - ) - - await trio.sleep_forever() - except BaseExceptionGroup as error: - _, other_errors = error.split((ShutdownError, KeyboardInterrupt)) - if other_errors is not None: - raise other_errors - finally: - await context.terminated.set() - server_nursery.cancel_scope.deadline = trio.current_time() + config.graceful_timeout - - await lifespan.wait_for_shutdown() - lifespan_nursery.cancel_scope.cancel() - - -def trio_worker( - config: Config, sockets: Optional[Sockets] = None, shutdown_event: Optional[EventType] = None -) -> None: - if sockets is not None: - for sock in sockets.secure_sockets: - sock.listen(config.backlog) - for sock in sockets.insecure_sockets: - sock.listen(config.backlog) - app = load_application(config.application_path, config.wsgi_max_body_size) - - shutdown_trigger = None - if shutdown_event is not None: - shutdown_trigger = partial(check_multiprocess_shutdown_event, shutdown_event, trio.sleep) - - trio.run(partial(worker_serve, app, config, sockets=sockets, shutdown_trigger=shutdown_trigger)) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/statsd.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/statsd.py deleted file mode 100644 index db04176..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/statsd.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import annotations - -import trio - -from ..config import Config -from ..statsd import StatsdLogger as Base - - -class StatsdLogger(Base): - def __init__(self, config: Config) -> None: - super().__init__(config) - self.address = tuple(config.statsd_host.rsplit(":", 1)) - self.socket = trio.socket.socket(trio.socket.AF_INET, trio.socket.SOCK_DGRAM) - - async def _socket_send(self, message: bytes) -> None: - await self.socket.sendto(message, self.address) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/task_group.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/task_group.py deleted file mode 100644 index 044ff85..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/task_group.py +++ /dev/null @@ -1,78 +0,0 @@ -from __future__ import annotations - -import sys -from types import TracebackType -from typing import Any, Awaitable, Callable, Optional - -import trio - -from ..config import Config -from ..typing import AppWrapper, ASGIReceiveCallable, ASGIReceiveEvent, ASGISendEvent, Scope - -if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - - -async def _handle( - app: AppWrapper, - config: Config, - scope: Scope, - receive: ASGIReceiveCallable, - send: Callable[[Optional[ASGISendEvent]], Awaitable[None]], - sync_spawn: Callable, - call_soon: Callable, -) -> None: - try: - await app(scope, receive, send, sync_spawn, call_soon) - except trio.Cancelled: - raise - except BaseExceptionGroup as error: - _, other_errors = error.split(trio.Cancelled) - if other_errors is not None: - await config.log.exception("Error in ASGI Framework") - await send(None) - else: - raise - except Exception: - await config.log.exception("Error in ASGI Framework") - finally: - await send(None) - - -class TaskGroup: - def __init__(self) -> None: - self._nursery: Optional[trio._core._run.Nursery] = None - self._nursery_manager: Optional[trio._core._run.NurseryManager] = None - - async def spawn_app( - self, - app: AppWrapper, - config: Config, - scope: Scope, - send: Callable[[Optional[ASGISendEvent]], Awaitable[None]], - ) -> Callable[[ASGIReceiveEvent], Awaitable[None]]: - app_send_channel, app_receive_channel = trio.open_memory_channel(config.max_app_queue_size) - self._nursery.start_soon( - _handle, - app, - config, - scope, - app_receive_channel.receive, - send, - trio.to_thread.run_sync, - trio.from_thread.run, - ) - return app_send_channel.send - - def spawn(self, func: Callable, *args: Any) -> None: - self._nursery.start_soon(func, *args) - - async def __aenter__(self) -> TaskGroup: - self._nursery_manager = trio.open_nursery() - self._nursery = await self._nursery_manager.__aenter__() - return self - - async def __aexit__(self, exc_type: type, exc_value: BaseException, tb: TracebackType) -> None: - await self._nursery_manager.__aexit__(exc_type, exc_value, tb) - self._nursery_manager = None - self._nursery = None diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/tcp_server.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/tcp_server.py deleted file mode 100644 index 7eb7711..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/tcp_server.py +++ /dev/null @@ -1,139 +0,0 @@ -from __future__ import annotations - -from math import inf -from typing import Any, Generator - -import trio - -from .task_group import TaskGroup -from .worker_context import TrioSingleTask, WorkerContext -from ..config import Config -from ..events import Closed, Event, RawData, Updated -from ..protocol import ProtocolWrapper -from ..typing import AppWrapper, ConnectionState, LifespanState -from ..utils import parse_socket_addr - -MAX_RECV = 2**16 - - -class TCPServer: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - state: LifespanState, - stream: trio.abc.Stream, - ) -> None: - self.app = app - self.config = config - self.context = context - self.protocol: ProtocolWrapper - self.send_lock = trio.Lock() - self.idle_task = TrioSingleTask() - self.stream = stream - self.state = state - - def __await__(self) -> Generator[Any, None, None]: - return self.run().__await__() - - async def run(self) -> None: - try: - try: - with trio.fail_after(self.config.ssl_handshake_timeout): - await self.stream.do_handshake() - except (trio.BrokenResourceError, trio.TooSlowError): - return # Handshake failed - alpn_protocol = self.stream.selected_alpn_protocol() - socket = self.stream.transport_stream.socket - ssl = True - except AttributeError: # Not SSL - alpn_protocol = "http/1.1" - socket = self.stream.socket - ssl = False - - try: - client = parse_socket_addr(socket.family, socket.getpeername()) - server = parse_socket_addr(socket.family, socket.getsockname()) - - async with TaskGroup() as task_group: - self._task_group = task_group - self.protocol = ProtocolWrapper( - self.app, - self.config, - self.context, - task_group, - ConnectionState(self.state.copy()), - ssl, - client, - server, - self.protocol_send, - alpn_protocol, - ) - await self.protocol.initiate() - await self.idle_task.restart(self._task_group, self._idle_timeout) - await self._read_data() - except OSError: - pass - finally: - await self._close() - - async def protocol_send(self, event: Event) -> None: - if isinstance(event, RawData): - async with self.send_lock: - try: - with trio.CancelScope() as cancel_scope: - cancel_scope.shield = True - await self.stream.send_all(event.data) - except (trio.BrokenResourceError, trio.ClosedResourceError): - await self.protocol.handle(Closed()) - elif isinstance(event, Closed): - await self._close() - await self.protocol.handle(Closed()) - elif isinstance(event, Updated): - if event.idle: - await self.idle_task.restart(self._task_group, self._idle_timeout) - else: - await self.idle_task.stop() - - async def _read_data(self) -> None: - while True: - try: - with trio.fail_after(self.config.read_timeout or inf): - data = await self.stream.receive_some(MAX_RECV) - except ( - trio.ClosedResourceError, - trio.BrokenResourceError, - trio.TooSlowError, - ): - break - else: - await self.protocol.handle(RawData(data)) - if data == b"": - break - await self.protocol.handle(Closed()) - - async def _close(self) -> None: - try: - await self.stream.send_eof() - except ( - trio.BrokenResourceError, - AttributeError, - trio.BusyResourceError, - trio.ClosedResourceError, - ): - # They're already gone, nothing to do - # Or it is a SSL stream - pass - await self.stream.aclose() - - async def _idle_timeout(self) -> None: - with trio.move_on_after(self.config.keep_alive_timeout): - await self.context.terminated.wait() - - with trio.CancelScope(shield=True): - await self._initiate_server_close() - - async def _initiate_server_close(self) -> None: - await self.protocol.handle(Closed()) - await self.stream.aclose() diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/udp_server.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/udp_server.py deleted file mode 100644 index d66b037..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/udp_server.py +++ /dev/null @@ -1,54 +0,0 @@ -from __future__ import annotations - -import trio - -from .task_group import TaskGroup -from .worker_context import WorkerContext -from ..config import Config -from ..events import Event, RawData -from ..typing import AppWrapper, ConnectionState, LifespanState -from ..utils import parse_socket_addr - -MAX_RECV = 2**16 - - -class UDPServer: - def __init__( - self, - app: AppWrapper, - config: Config, - context: WorkerContext, - state: LifespanState, - socket: trio.socket.socket, - ) -> None: - self.app = app - self.config = config - self.context = context - self.socket = trio.socket.from_stdlib_socket(socket) - self.state = state - - async def run( - self, task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED - ) -> None: - from ..protocol.quic import QuicProtocol # h3/Quic is an optional part of Hypercorn - - task_status.started() - server = parse_socket_addr(self.socket.family, self.socket.getsockname()) - async with TaskGroup() as task_group: - self.protocol = QuicProtocol( - self.app, - self.config, - self.context, - task_group, - ConnectionState(self.state.copy()), - server, - self.protocol_send, - ) - - while not self.context.terminated.is_set() or not self.protocol.idle: - data, address = await self.socket.recvfrom(MAX_RECV) - await self.protocol.handle(RawData(data=data, address=address)) - - async def protocol_send(self, event: Event) -> None: - if isinstance(event, RawData): - await self.socket.sendto(event.data, event.address) diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/trio/worker_context.py b/serverenv/lib/python3.9/site-packages/hypercorn/trio/worker_context.py deleted file mode 100644 index dddcf42..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/trio/worker_context.py +++ /dev/null @@ -1,83 +0,0 @@ -from __future__ import annotations - -from functools import wraps -from typing import Awaitable, Callable, Optional, Type, Union - -import trio - -from ..typing import Event, SingleTask, TaskGroup - - -def _cancel_wrapper(func: Callable[[], Awaitable[None]]) -> Callable[[], Awaitable[None]]: - @wraps(func) - async def wrapper( - task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED, - ) -> None: - cancel_scope = trio.CancelScope() - task_status.started(cancel_scope) - with cancel_scope: - await func() - - return wrapper - - -class TrioSingleTask: - def __init__(self) -> None: - self._handle: Optional[trio.CancelScope] = None - self._lock = trio.Lock() - - async def restart(self, task_group: TaskGroup, action: Callable) -> None: - async with self._lock: - if self._handle is not None: - self._handle.cancel() - self._handle = await task_group._nursery.start(_cancel_wrapper(action)) # type: ignore - - async def stop(self) -> None: - async with self._lock: - if self._handle is not None: - self._handle.cancel() - self._handle = None - - -class EventWrapper: - def __init__(self) -> None: - self._event = trio.Event() - - async def clear(self) -> None: - self._event = trio.Event() - - async def wait(self) -> None: - await self._event.wait() - - async def set(self) -> None: - self._event.set() - - def is_set(self) -> bool: - return self._event.is_set() - - -class WorkerContext: - event_class: Type[Event] = EventWrapper - single_task_class: Type[SingleTask] = TrioSingleTask - - def __init__(self, max_requests: Optional[int]) -> None: - self.max_requests = max_requests - self.requests = 0 - self.terminate = self.event_class() - self.terminated = self.event_class() - - async def mark_request(self) -> None: - if self.max_requests is None: - return - - self.requests += 1 - if self.requests > self.max_requests: - await self.terminate.set() - - @staticmethod - async def sleep(wait: Union[float, int]) -> None: - return await trio.sleep(wait) - - @staticmethod - def time() -> float: - return trio.current_time() diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/typing.py b/serverenv/lib/python3.9/site-packages/hypercorn/typing.py deleted file mode 100644 index cba7d5d..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/typing.py +++ /dev/null @@ -1,375 +0,0 @@ -from __future__ import annotations - -from multiprocessing.synchronize import Event as EventType -from types import TracebackType -from typing import ( - Any, - Awaitable, - Callable, - Dict, - Iterable, - Literal, - NewType, - Optional, - Protocol, - Tuple, - Type, - TypedDict, - Union, -) - -import h2.events -import h11 - -from .config import Config, Sockets - -try: - from typing import NotRequired -except ImportError: - from typing_extensions import NotRequired - -H11SendableEvent = Union[h11.Data, h11.EndOfMessage, h11.InformationalResponse, h11.Response] - -WorkerFunc = Callable[[Config, Optional[Sockets], Optional[EventType]], None] - -LifespanState = Dict[str, Any] - -ConnectionState = NewType("ConnectionState", Dict[str, Any]) - - -class ASGIVersions(TypedDict, total=False): - spec_version: str - version: Union[Literal["2.0"], Literal["3.0"]] - - -class HTTPScope(TypedDict): - type: Literal["http"] - asgi: ASGIVersions - http_version: str - method: str - scheme: str - path: str - raw_path: bytes - query_string: bytes - root_path: str - headers: Iterable[Tuple[bytes, bytes]] - client: Optional[Tuple[str, int]] - server: Optional[Tuple[str, Optional[int]]] - state: ConnectionState - extensions: Dict[str, dict] - - -class WebsocketScope(TypedDict): - type: Literal["websocket"] - asgi: ASGIVersions - http_version: str - scheme: str - path: str - raw_path: bytes - query_string: bytes - root_path: str - headers: Iterable[Tuple[bytes, bytes]] - client: Optional[Tuple[str, int]] - server: Optional[Tuple[str, Optional[int]]] - subprotocols: Iterable[str] - state: ConnectionState - extensions: Dict[str, dict] - - -class LifespanScope(TypedDict): - type: Literal["lifespan"] - asgi: ASGIVersions - state: LifespanState - - -WWWScope = Union[HTTPScope, WebsocketScope] -Scope = Union[HTTPScope, WebsocketScope, LifespanScope] - - -class HTTPRequestEvent(TypedDict): - type: Literal["http.request"] - body: bytes - more_body: bool - - -class HTTPResponseStartEvent(TypedDict): - type: Literal["http.response.start"] - status: int - headers: Iterable[Tuple[bytes, bytes]] - trailers: NotRequired[bool] - - -class HTTPResponseBodyEvent(TypedDict): - type: Literal["http.response.body"] - body: bytes - more_body: bool - - -class HTTPResponseTrailersEvent(TypedDict): - type: Literal["http.response.trailers"] - headers: Iterable[Tuple[bytes, bytes]] - more_trailers: NotRequired[bool] - - -class HTTPServerPushEvent(TypedDict): - type: Literal["http.response.push"] - path: str - headers: Iterable[Tuple[bytes, bytes]] - - -class HTTPEarlyHintEvent(TypedDict): - type: Literal["http.response.early_hint"] - links: Iterable[bytes] - - -class HTTPDisconnectEvent(TypedDict): - type: Literal["http.disconnect"] - - -class WebsocketConnectEvent(TypedDict): - type: Literal["websocket.connect"] - - -class WebsocketAcceptEvent(TypedDict): - type: Literal["websocket.accept"] - subprotocol: Optional[str] - headers: Iterable[Tuple[bytes, bytes]] - - -class WebsocketReceiveEvent(TypedDict): - type: Literal["websocket.receive"] - bytes: Optional[bytes] - text: Optional[str] - - -class WebsocketSendEvent(TypedDict): - type: Literal["websocket.send"] - bytes: Optional[bytes] - text: Optional[str] - - -class WebsocketResponseStartEvent(TypedDict): - type: Literal["websocket.http.response.start"] - status: int - headers: Iterable[Tuple[bytes, bytes]] - - -class WebsocketResponseBodyEvent(TypedDict): - type: Literal["websocket.http.response.body"] - body: bytes - more_body: bool - - -class WebsocketDisconnectEvent(TypedDict): - type: Literal["websocket.disconnect"] - code: int - - -class WebsocketCloseEvent(TypedDict): - type: Literal["websocket.close"] - code: int - reason: Optional[str] - - -class LifespanStartupEvent(TypedDict): - type: Literal["lifespan.startup"] - - -class LifespanShutdownEvent(TypedDict): - type: Literal["lifespan.shutdown"] - - -class LifespanStartupCompleteEvent(TypedDict): - type: Literal["lifespan.startup.complete"] - - -class LifespanStartupFailedEvent(TypedDict): - type: Literal["lifespan.startup.failed"] - message: str - - -class LifespanShutdownCompleteEvent(TypedDict): - type: Literal["lifespan.shutdown.complete"] - - -class LifespanShutdownFailedEvent(TypedDict): - type: Literal["lifespan.shutdown.failed"] - message: str - - -ASGIReceiveEvent = Union[ - HTTPRequestEvent, - HTTPDisconnectEvent, - WebsocketConnectEvent, - WebsocketReceiveEvent, - WebsocketDisconnectEvent, - LifespanStartupEvent, - LifespanShutdownEvent, -] - - -ASGISendEvent = Union[ - HTTPResponseStartEvent, - HTTPResponseBodyEvent, - HTTPResponseTrailersEvent, - HTTPServerPushEvent, - HTTPEarlyHintEvent, - HTTPDisconnectEvent, - WebsocketAcceptEvent, - WebsocketSendEvent, - WebsocketResponseStartEvent, - WebsocketResponseBodyEvent, - WebsocketCloseEvent, - LifespanStartupCompleteEvent, - LifespanStartupFailedEvent, - LifespanShutdownCompleteEvent, - LifespanShutdownFailedEvent, -] - - -ASGIReceiveCallable = Callable[[], Awaitable[ASGIReceiveEvent]] -ASGISendCallable = Callable[[ASGISendEvent], Awaitable[None]] - -ASGIFramework = Callable[ - [ - Scope, - ASGIReceiveCallable, - ASGISendCallable, - ], - Awaitable[None], -] -WSGIFramework = Callable[[dict, Callable], Iterable[bytes]] -Framework = Union[ASGIFramework, WSGIFramework] - - -class H2SyncStream(Protocol): - scope: dict - - def data_received(self, data: bytes) -> None: - pass - - def ended(self) -> None: - pass - - def reset(self) -> None: - pass - - def close(self) -> None: - pass - - async def handle_request( - self, - event: h2.events.RequestReceived, - scheme: str, - client: Tuple[str, int], - server: Tuple[str, int], - ) -> None: - pass - - -class H2AsyncStream(Protocol): - scope: dict - - async def data_received(self, data: bytes) -> None: - pass - - async def ended(self) -> None: - pass - - async def reset(self) -> None: - pass - - async def close(self) -> None: - pass - - async def handle_request( - self, - event: h2.events.RequestReceived, - scheme: str, - client: Tuple[str, int], - server: Tuple[str, int], - ) -> None: - pass - - -class Event(Protocol): - def __init__(self) -> None: - pass - - async def clear(self) -> None: - pass - - async def set(self) -> None: - pass - - async def wait(self) -> None: - pass - - def is_set(self) -> bool: - pass - - -class WorkerContext(Protocol): - event_class: Type[Event] - single_task_class: Type[SingleTask] - terminate: Event - terminated: Event - - async def mark_request(self) -> None: - pass - - @staticmethod - async def sleep(wait: Union[float, int]) -> None: - pass - - @staticmethod - def time() -> float: - pass - - -class TaskGroup(Protocol): - async def spawn_app( - self, - app: AppWrapper, - config: Config, - scope: Scope, - send: Callable[[Optional[ASGISendEvent]], Awaitable[None]], - ) -> Callable[[ASGIReceiveEvent], Awaitable[None]]: - pass - - def spawn(self, func: Callable, *args: Any) -> None: - pass - - async def __aenter__(self) -> TaskGroup: - pass - - async def __aexit__(self, exc_type: type, exc_value: BaseException, tb: TracebackType) -> None: - pass - - -class ResponseSummary(TypedDict): - status: int - headers: Iterable[Tuple[bytes, bytes]] - - -class AppWrapper(Protocol): - async def __call__( - self, - scope: Scope, - receive: ASGIReceiveCallable, - send: ASGISendCallable, - sync_spawn: Callable, - call_soon: Callable, - ) -> None: - pass - - -class SingleTask(Protocol): - def __init__(self) -> None: - pass - - async def restart(self, task_group: TaskGroup, action: Callable) -> None: - pass - - async def stop(self) -> None: - pass diff --git a/serverenv/lib/python3.9/site-packages/hypercorn/utils.py b/serverenv/lib/python3.9/site-packages/hypercorn/utils.py deleted file mode 100644 index 39249c5..0000000 --- a/serverenv/lib/python3.9/site-packages/hypercorn/utils.py +++ /dev/null @@ -1,219 +0,0 @@ -from __future__ import annotations - -import inspect -import os -import socket -import sys -from enum import Enum -from importlib import import_module -from multiprocessing.synchronize import Event as EventType -from pathlib import Path -from typing import ( - Any, - Awaitable, - Callable, - cast, - Dict, - Iterable, - List, - Literal, - Optional, - Tuple, - TYPE_CHECKING, -) - -from .app_wrappers import ASGIWrapper, WSGIWrapper -from .config import Config -from .typing import AppWrapper, ASGIFramework, Framework, WSGIFramework - -if TYPE_CHECKING: - from .protocol.events import Request - - -class ShutdownError(Exception): - pass - - -class NoAppError(Exception): - pass - - -class LifespanTimeoutError(Exception): - def __init__(self, stage: str) -> None: - super().__init__( - f"Timeout whilst awaiting {stage}. Your application may not support the ASGI Lifespan " - f"protocol correctly, alternatively the {stage}_timeout configuration is incorrect." - ) - - -class LifespanFailureError(Exception): - def __init__(self, stage: str, message: str) -> None: - super().__init__(f"Lifespan failure in {stage}. '{message}'") - - -class UnexpectedMessageError(Exception): - def __init__(self, state: Enum, message_type: str) -> None: - super().__init__(f"Unexpected message type, {message_type} given the state {state}") - - -class FrameTooLargeError(Exception): - pass - - -def suppress_body(method: str, status_code: int) -> bool: - return method == "HEAD" or 100 <= status_code < 200 or status_code in {204, 304} - - -def build_and_validate_headers(headers: Iterable[Tuple[bytes, bytes]]) -> List[Tuple[bytes, bytes]]: - # Validates that the header name and value are bytes - validated_headers: List[Tuple[bytes, bytes]] = [] - for name, value in headers: - if name[0] == b":"[0]: - raise ValueError("Pseudo headers are not valid") - validated_headers.append((bytes(name).strip(), bytes(value).strip())) - return validated_headers - - -def filter_pseudo_headers(headers: List[Tuple[bytes, bytes]]) -> List[Tuple[bytes, bytes]]: - filtered_headers: List[Tuple[bytes, bytes]] = [(b"host", b"")] # Placeholder - authority = None - host = b"" - for name, value in headers: - if name == b":authority": # h2 & h3 libraries validate this is present - authority = value - elif name == b"host": - host = value - elif name[0] != b":"[0]: - filtered_headers.append((name, value)) - filtered_headers[0] = (b"host", authority if authority is not None else host) - return filtered_headers - - -def load_application(path: str, wsgi_max_body_size: int) -> AppWrapper: - mode: Optional[Literal["asgi", "wsgi"]] = None - if ":" not in path: - module_name, app_name = path, "app" - elif path.count(":") == 2: - mode, module_name, app_name = path.split(":", 2) # type: ignore - if mode not in {"asgi", "wsgi"}: - raise ValueError("Invalid mode, must be 'asgi', or 'wsgi'") - else: - module_name, app_name = path.split(":", 1) - - module_path = Path(module_name).resolve() - sys.path.insert(0, str(module_path.parent)) - if module_path.is_file(): - import_name = module_path.with_suffix("").name - else: - import_name = module_path.name - try: - module = import_module(import_name) - except ModuleNotFoundError as error: - if error.name == import_name: - raise NoAppError(f"Cannot load application from '{path}', module not found.") - else: - raise - try: - app = eval(app_name, vars(module)) - except NameError: - raise NoAppError(f"Cannot load application from '{path}', application not found.") - else: - return wrap_app(app, wsgi_max_body_size, mode) - - -def wrap_app( - app: Framework, wsgi_max_body_size: int, mode: Optional[Literal["asgi", "wsgi"]] -) -> AppWrapper: - if mode is None: - mode = "asgi" if is_asgi(app) else "wsgi" - if mode == "asgi": - return ASGIWrapper(cast(ASGIFramework, app)) - else: - return WSGIWrapper(cast(WSGIFramework, app), wsgi_max_body_size) - - -def files_to_watch() -> Dict[Path, float]: - last_updates: Dict[Path, float] = {} - for module in list(sys.modules.values()): - filename = getattr(module, "__file__", None) - if filename is None: - continue - path = Path(filename) - try: - last_updates[Path(filename)] = path.stat().st_mtime - except (FileNotFoundError, NotADirectoryError): - pass - return last_updates - - -def check_for_updates(files: Dict[Path, float]) -> bool: - for path, last_mtime in files.items(): - try: - mtime = path.stat().st_mtime - except FileNotFoundError: - return True - else: - if mtime > last_mtime: - return True - else: - files[path] = mtime - return False - - -async def raise_shutdown(shutdown_event: Callable[..., Awaitable]) -> None: - await shutdown_event() - raise ShutdownError() - - -async def check_multiprocess_shutdown_event( - shutdown_event: EventType, sleep: Callable[[float], Awaitable[Any]] -) -> None: - while True: - if shutdown_event.is_set(): - return - await sleep(0.1) - - -def write_pid_file(pid_path: str) -> None: - with open(pid_path, "w") as file_: - file_.write(f"{os.getpid()}") - - -def parse_socket_addr(family: int, address: tuple) -> Optional[Tuple[str, int]]: - if family == socket.AF_INET: - return address - elif family == socket.AF_INET6: - return (address[0], address[1]) - else: - return None - - -def repr_socket_addr(family: int, address: tuple) -> str: - if family == socket.AF_INET: - return f"{address[0]}:{address[1]}" - elif family == socket.AF_INET6: - return f"[{address[0]}]:{address[1]}" - elif family == socket.AF_UNIX: - return f"unix:{address}" - else: - return f"{address}" - - -def valid_server_name(config: Config, request: "Request") -> bool: - if len(config.server_names) == 0: - return True - - host = "" - for name, value in request.headers: - if name.lower() == b"host": - host = value.decode() - break - return host in config.server_names - - -def is_asgi(app: Any) -> bool: - if inspect.iscoroutinefunction(app): - return True - elif hasattr(app, "__call__"): - return inspect.iscoroutinefunction(app.__call__) - return False diff --git a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/LICENSE b/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/LICENSE deleted file mode 100644 index d24c351..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Cory Benfield - -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/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/METADATA deleted file mode 100644 index bf81d5f..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/METADATA +++ /dev/null @@ -1,98 +0,0 @@ -Metadata-Version: 2.2 -Name: hyperframe -Version: 6.1.0 -Summary: Pure-Python HTTP/2 framing -Author-email: Cory Benfield -Maintainer-email: Thomas Kriechbaumer -License: The MIT License (MIT) - - Copyright (c) 2014 Cory Benfield - - 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. - -Project-URL: Homepage, https://github.com/python-hyper/hyperframe/ -Project-URL: Bug Reports, https://github.com/python-hyper/hyperframe/issues -Project-URL: Source, https://github.com/python-hyper/hyperframe/ -Project-URL: Documentation, https://python-hyper.org/ -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.9 -Description-Content-Type: text/x-rst -License-File: LICENSE - -====================================== -hyperframe: Pure-Python HTTP/2 framing -====================================== - -.. image:: https://github.com/python-hyper/hyperframe/workflows/CI/badge.svg - :target: https://github.com/python-hyper/hyperframe/actions - :alt: Build Status -.. image:: https://codecov.io/gh/python-hyper/hyperframe/branch/master/graph/badge.svg - :target: https://codecov.io/gh/python-hyper/hyperframe - :alt: Code Coverage -.. image:: https://readthedocs.org/projects/hyperframe/badge/?version=latest - :target: https://hyperframe.readthedocs.io/en/latest/ - :alt: Documentation Status -.. image:: https://img.shields.io/badge/chat-join_now-brightgreen.svg - :target: https://gitter.im/python-hyper/community - :alt: Chat community - -This library contains the HTTP/2 framing code used in the `hyper`_ project. It -provides a pure-Python codebase that is capable of decoding a binary stream -into HTTP/2 frames. - -This library is used directly by `hyper`_ and a number of other projects to -provide HTTP/2 frame decoding logic. - -Contributing -============ - -hyperframe welcomes contributions from anyone! Unlike many other projects we -are happy to accept cosmetic contributions and small contributions, in addition -to large feature requests and changes. - -Before you contribute (either by opening an issue or filing a pull request), -please `read the contribution guidelines`_. - -.. _read the contribution guidelines: http://hyper.readthedocs.org/en/development/contributing.html - -License -======= - -hyperframe is made available under the MIT License. For more details, see the -``LICENSE`` file in the repository. - -Authors -======= - -hyperframe is maintained by Cory Benfield, with contributions from others. For -more details about the contributors, please see ``CONTRIBUTORS.rst``. - -.. _hyper: http://python-hyper.org/ diff --git a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/RECORD deleted file mode 100644 index df946b5..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/RECORD +++ /dev/null @@ -1,15 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hyperframe/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hyperframe/exceptions.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hyperframe/flags.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/hyperframe/frame.cpython-39.pyc,, -hyperframe-6.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -hyperframe-6.1.0.dist-info/LICENSE,sha256=djqTQqBN9iBGydx0ilKHk06wpTMcaGOzygruIOGMtO0,1080 -hyperframe-6.1.0.dist-info/METADATA,sha256=op9XkrlFm0dliASYhSAAkVbvjC3qZgIsKWmhRQZbrWk,4339 -hyperframe-6.1.0.dist-info/RECORD,, -hyperframe-6.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91 -hyperframe-6.1.0.dist-info/top_level.txt,sha256=aIXWNxzKF_jwE8lyWG5Paqn5RP7PDBYeguraia-oHJE,11 -hyperframe/__init__.py,sha256=Q_MBdkIECWTLvksOXg5nYHUX8jA8hhoQsuj6OUQ24lI,111 -hyperframe/exceptions.py,sha256=DZLrZw5y7MLBMRkxCxrqf5Ehz8BoE2n7MpVap4D5vcI,1516 -hyperframe/flags.py,sha256=9lvpaeKXrfYeuxj8Xeq21ED40ODTipo3ZXeDUiX5WZI,1294 -hyperframe/frame.py,sha256=asYhkhkOr1vRB3fuZYE1HIhTIFD0JNOWWwZ8vedzWxU,31659 -hyperframe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/WHEEL deleted file mode 100644 index 505164b..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (75.8.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/top_level.txt b/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/top_level.txt deleted file mode 100644 index b21bb7c..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe-6.1.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -hyperframe diff --git a/serverenv/lib/python3.9/site-packages/hyperframe/__init__.py b/serverenv/lib/python3.9/site-packages/hyperframe/__init__.py deleted file mode 100644 index e95b20b..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -""" -Provides a pure-Python HTTP/2 framing layer. -""" -from __future__ import annotations - -__version__ = "6.1.0" diff --git a/serverenv/lib/python3.9/site-packages/hyperframe/exceptions.py b/serverenv/lib/python3.9/site-packages/hyperframe/exceptions.py deleted file mode 100644 index 7a40f4a..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe/exceptions.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Exceptions that can be thrown by hyperframe. -""" -from __future__ import annotations - - -class HyperframeError(Exception): - """ - The base class for all exceptions for the hyperframe module. - - .. versionadded:: 6.0.0 - """ - - -class UnknownFrameError(HyperframeError): - """ - A frame of unknown type was received. - - .. versionchanged:: 6.0.0 - Changed base class from `ValueError` to :class:`HyperframeError` - """ - - def __init__(self, frame_type: int, length: int) -> None: - #: The type byte of the unknown frame that was received. - self.frame_type = frame_type - - #: The length of the data portion of the unknown frame. - self.length = length - - def __str__(self) -> str: - return ( - f"UnknownFrameError: Unknown frame type 0x{self.frame_type:X} received, length {self.length} bytes" - ) - - -class InvalidPaddingError(HyperframeError): - """ - A frame with invalid padding was received. - - .. versionchanged:: 6.0.0 - Changed base class from `ValueError` to :class:`HyperframeError` - """ - - -class InvalidFrameError(HyperframeError): - """ - Parsing a frame failed because the data was not laid out appropriately. - - .. versionadded:: 3.0.2 - - .. versionchanged:: 6.0.0 - Changed base class from `ValueError` to :class:`HyperframeError` - """ - - -class InvalidDataError(HyperframeError): - """ - Content or data of a frame was is invalid or violates the specification. - - .. versionadded:: 6.0.0 - """ diff --git a/serverenv/lib/python3.9/site-packages/hyperframe/flags.py b/serverenv/lib/python3.9/site-packages/hyperframe/flags.py deleted file mode 100644 index e5f4a22..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe/flags.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic Flag and Flags data structures. -""" -from __future__ import annotations - -from collections.abc import Iterable, Iterator, MutableSet -from typing import NamedTuple - - -class Flag(NamedTuple): - name: str - bit: int - - -class Flags(MutableSet): # type: ignore - """ - A simple MutableSet implementation that will only accept known flags as - elements. - - Will behave like a regular set(), except that a ValueError will be thrown - when .add()ing unexpected flags. - """ - - def __init__(self, defined_flags: Iterable[Flag]) -> None: - self._valid_flags = {flag.name for flag in defined_flags} - self._flags: set[str] = set() - - def __repr__(self) -> str: - return repr(sorted(self._flags)) - - def __contains__(self, x: object) -> bool: - return self._flags.__contains__(x) - - def __iter__(self) -> Iterator[str]: - return self._flags.__iter__() - - def __len__(self) -> int: - return self._flags.__len__() - - def discard(self, value: str) -> None: - return self._flags.discard(value) - - def add(self, value: str) -> None: - if value not in self._valid_flags: - msg = f"Unexpected flag: {value}. Valid flags are: {self._valid_flags}" - raise ValueError(msg) - return self._flags.add(value) diff --git a/serverenv/lib/python3.9/site-packages/hyperframe/frame.py b/serverenv/lib/python3.9/site-packages/hyperframe/frame.py deleted file mode 100644 index a67487e..0000000 --- a/serverenv/lib/python3.9/site-packages/hyperframe/frame.py +++ /dev/null @@ -1,937 +0,0 @@ -""" -Framing logic for HTTP/2. - -Provides both classes to represent framed -data and logic for aiding the connection when it comes to reading from the -socket. -""" -from __future__ import annotations - -import binascii -import struct -from typing import TYPE_CHECKING, Any - -if TYPE_CHECKING: - from collections.abc import Iterable # pragma: no cover - -from .exceptions import InvalidDataError, InvalidFrameError, InvalidPaddingError, UnknownFrameError -from .flags import Flag, Flags - -# The maximum initial length of a frame. Some frames have shorter maximum -# lengths. -FRAME_MAX_LEN = (2 ** 14) - -# The maximum allowed length of a frame. -FRAME_MAX_ALLOWED_LEN = (2 ** 24) - 1 - -# Stream association enumerations. -_STREAM_ASSOC_HAS_STREAM = "has-stream" -_STREAM_ASSOC_NO_STREAM = "no-stream" -_STREAM_ASSOC_EITHER = "either" - -# Structs for packing and unpacking -_STRUCT_HBBBL = struct.Struct(">HBBBL") -_STRUCT_LL = struct.Struct(">LL") -_STRUCT_HL = struct.Struct(">HL") -_STRUCT_LB = struct.Struct(">LB") -_STRUCT_L = struct.Struct(">L") -_STRUCT_H = struct.Struct(">H") -_STRUCT_B = struct.Struct(">B") - - -class Frame: - """ - The base class for all HTTP/2 frames. - """ - - #: The flags defined on this type of frame. - defined_flags: list[Flag] = [] - - #: The byte used to define the type of the frame. - type: int | None = None - - # If 'has-stream', the frame's stream_id must be non-zero. If 'no-stream', - # it must be zero. If 'either', it's not checked. - stream_association: str | None = None - - def __init__(self, stream_id: int, flags: Iterable[str] = ()) -> None: - #: The stream identifier for the stream this frame was received on. - #: Set to 0 for frames sent on the connection (stream-id 0). - self.stream_id = stream_id - - #: The flags set for this frame. - self.flags = Flags(self.defined_flags) - - #: The frame length, excluding the nine-byte header. - self.body_len = 0 - - for flag in flags: - self.flags.add(flag) - - if not self.stream_id and self.stream_association == _STREAM_ASSOC_HAS_STREAM: - msg = f"Stream ID must be non-zero for {type(self).__name__}" - raise InvalidDataError(msg) - if self.stream_id and self.stream_association == _STREAM_ASSOC_NO_STREAM: - msg = f"Stream ID must be zero for {type(self).__name__} with stream_id={self.stream_id}" - raise InvalidDataError(msg) - - def __repr__(self) -> str: - return ( - f"{type(self).__name__}(stream_id={self.stream_id}, flags={self.flags!r}): {self._body_repr()}" - ) - - def _body_repr(self) -> str: - # More specific implementation may be provided by subclasses of Frame. - # This fallback shows the serialized (and truncated) body content. - return _raw_data_repr(self.serialize_body()) - - @staticmethod - def explain(data: memoryview) -> tuple[Frame, int]: - """ - Takes a bytestring and tries to parse a single frame and print it. - - This function is only provided for debugging purposes. - - :param data: A memoryview object containing the raw data of at least - one complete frame (header and body). - - .. versionadded:: 6.0.0 - """ - frame, length = Frame.parse_frame_header(data[:9]) - frame.parse_body(data[9:9 + length]) - print(frame) # noqa: T201 - return frame, length - - @staticmethod - def parse_frame_header(header: memoryview, strict: bool = False) -> tuple[Frame, int]: - """ - Takes a 9-byte frame header and returns a tuple of the appropriate - Frame object and the length that needs to be read from the socket. - - This populates the flags field, and determines how long the body is. - - :param header: A memoryview object containing the 9-byte frame header - data of a frame. Must not contain more or less. - - :param strict: Whether to raise an exception when encountering a frame - not defined by spec and implemented by hyperframe. - - :raises hyperframe.exceptions.UnknownFrameError: If a frame of unknown - type is received. - - .. versionchanged:: 5.0.0 - Added ``strict`` parameter to accommodate :class:`ExtensionFrame` - """ - try: - fields = _STRUCT_HBBBL.unpack(header) - except struct.error as err: - msg = "Invalid frame header" - raise InvalidFrameError(msg) from err - - # First 24 bits are frame length. - length = (fields[0] << 8) + fields[1] - typ_e = fields[2] - flags = fields[3] - stream_id = fields[4] & 0x7FFFFFFF - - try: - frame = FRAMES[typ_e](stream_id) - except KeyError as err: - if strict: - raise UnknownFrameError(typ_e, length) from err - frame = ExtensionFrame(type=typ_e, stream_id=stream_id) - - frame.parse_flags(flags) - return (frame, length) - - def parse_flags(self, flag_byte: int) -> Flags: - for flag, flag_bit in self.defined_flags: - if flag_byte & flag_bit: - self.flags.add(flag) - - return self.flags - - def serialize(self) -> bytes: - """ - Convert a frame into a bytestring, representing the serialized form of - the frame. - """ - body = self.serialize_body() - self.body_len = len(body) - - # Build the common frame header. - # First, get the flags. - flags = 0 - - for flag, flag_bit in self.defined_flags: - if flag in self.flags: - flags |= flag_bit - - header = _STRUCT_HBBBL.pack( - (self.body_len >> 8) & 0xFFFF, # Length spread over top 24 bits - self.body_len & 0xFF, - self.type, - flags, - self.stream_id & 0x7FFFFFFF, # Stream ID is 32 bits. - ) - - return header + body - - def serialize_body(self) -> bytes: - raise NotImplementedError - - def parse_body(self, data: memoryview) -> None: - """ - Given the body of a frame, parses it into frame data. This populates - the non-header parts of the frame: that is, it does not populate the - stream ID or flags. - - :param data: A memoryview object containing the body data of the frame. - Must not contain *more* data than the length returned by - :meth:`parse_frame_header - `. - """ - raise NotImplementedError - - -class Padding: - """ - Mixin for frames that contain padding. Defines extra fields that can be - used and set by frames that can be padded. - """ - - def __init__(self, stream_id: int, pad_length: int = 0, **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) # type: ignore - - #: The length of the padding to use. - self.pad_length = pad_length - - def serialize_padding_data(self) -> bytes: - if "PADDED" in self.flags: # type: ignore - return _STRUCT_B.pack(self.pad_length) - return b"" - - def parse_padding_data(self, data: memoryview) -> int: - if "PADDED" in self.flags: # type: ignore - try: - self.pad_length = struct.unpack("!B", data[:1])[0] - except struct.error as err: - msg = "Invalid Padding data" - raise InvalidFrameError(msg) from err - return 1 - return 0 - - #: .. deprecated:: 5.2.1 - #: Use self.pad_length instead. - @property - def total_padding(self) -> int: # pragma: no cover - import warnings - warnings.warn( - "total_padding contains the same information as pad_length.", - DeprecationWarning, - stacklevel=2, - ) - return self.pad_length - - -class Priority: - """ - Mixin for frames that contain priority data. Defines extra fields that can - be used and set by frames that contain priority data. - """ - - def __init__(self, - stream_id: int, - depends_on: int = 0x0, - stream_weight: int = 0x0, - exclusive: bool = False, - **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) # type: ignore - - #: The stream ID of the stream on which this stream depends. - self.depends_on = depends_on - - #: The weight of the stream. This is an integer between 0 and 256. - self.stream_weight = stream_weight - - #: Whether the exclusive bit was set. - self.exclusive = exclusive - - def serialize_priority_data(self) -> bytes: - return _STRUCT_LB.pack( - self.depends_on + (0x80000000 if self.exclusive else 0), - self.stream_weight, - ) - - def parse_priority_data(self, data: memoryview) -> int: - try: - self.depends_on, self.stream_weight = _STRUCT_LB.unpack(data[:5]) - except struct.error as err: - msg = "Invalid Priority data" - raise InvalidFrameError(msg) from err - - self.exclusive = bool(self.depends_on >> 31) - self.depends_on &= 0x7FFFFFFF - return 5 - - -class DataFrame(Padding, Frame): - """ - DATA frames convey arbitrary, variable-length sequences of octets - associated with a stream. One or more DATA frames are used, for instance, - to carry HTTP request or response payloads. - """ - - #: The flags defined for DATA frames. - defined_flags = [ - Flag("END_STREAM", 0x01), - Flag("PADDED", 0x08), - ] - - #: The type byte for data frames. - type = 0x0 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id: int, data: bytes = b"", **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The data contained on this frame. - self.data = data - - def serialize_body(self) -> bytes: - padding_data = self.serialize_padding_data() - padding = b"\0" * self.pad_length - if isinstance(self.data, memoryview): - self.data = self.data.tobytes() - return b"".join([padding_data, self.data, padding]) - - def parse_body(self, data: memoryview) -> None: - padding_data_length = self.parse_padding_data(data) - self.data = ( - data[padding_data_length:len(data)-self.pad_length].tobytes() - ) - self.body_len = len(data) - - if self.pad_length and self.pad_length >= self.body_len: - msg = "Padding is too long." - raise InvalidPaddingError(msg) - - @property - def flow_controlled_length(self) -> int: - """ - The length of the frame that needs to be accounted for when considering - flow control. - """ - padding_len = 0 - if "PADDED" in self.flags: - # Account for extra 1-byte padding length field, which is still - # present if possibly zero-valued. - padding_len = self.pad_length + 1 - return len(self.data) + padding_len - - -class PriorityFrame(Priority, Frame): - """ - The PRIORITY frame specifies the sender-advised priority of a stream. It - can be sent at any time for an existing stream. This enables - reprioritisation of existing streams. - """ - - #: The flags defined for PRIORITY frames. - defined_flags: list[Flag] = [] - - #: The type byte defined for PRIORITY frames. - type = 0x02 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def _body_repr(self) -> str: - return f"exclusive={self.exclusive}, depends_on={self.depends_on}, stream_weight={self.stream_weight}" - - def serialize_body(self) -> bytes: - return self.serialize_priority_data() - - def parse_body(self, data: memoryview) -> None: - if len(data) > 5: - msg = f"PRIORITY must have 5 byte body: actual length {len(data)}." - raise InvalidFrameError(msg) - - self.parse_priority_data(data) - self.body_len = 5 - - -class RstStreamFrame(Frame): - """ - The RST_STREAM frame allows for abnormal termination of a stream. When sent - by the initiator of a stream, it indicates that they wish to cancel the - stream or that an error condition has occurred. When sent by the receiver - of a stream, it indicates that either the receiver is rejecting the stream, - requesting that the stream be cancelled or that an error condition has - occurred. - """ - - #: The flags defined for RST_STREAM frames. - defined_flags: list[Flag] = [] - - #: The type byte defined for RST_STREAM frames. - type = 0x03 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id: int, error_code: int = 0, **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The error code used when resetting the stream. - self.error_code = error_code - - def _body_repr(self) -> str: - return f"error_code={self.error_code}" - - def serialize_body(self) -> bytes: - return _STRUCT_L.pack(self.error_code) - - def parse_body(self, data: memoryview) -> None: - if len(data) != 4: - msg = f"RST_STREAM must have 4 byte body: actual length {len(data)}." - raise InvalidFrameError(msg) - - try: - self.error_code = _STRUCT_L.unpack(data)[0] - except struct.error as err: # pragma: no cover - msg = "Invalid RST_STREAM body" - raise InvalidFrameError(msg) from err - - self.body_len = 4 - - -class SettingsFrame(Frame): - """ - The SETTINGS frame conveys configuration parameters that affect how - endpoints communicate. The parameters are either constraints on peer - behavior or preferences. - - Settings are not negotiated. Settings describe characteristics of the - sending peer, which are used by the receiving peer. Different values for - the same setting can be advertised by each peer. For example, a client - might set a high initial flow control window, whereas a server might set a - lower value to conserve resources. - """ - - #: The flags defined for SETTINGS frames. - defined_flags = [Flag("ACK", 0x01)] - - #: The type byte defined for SETTINGS frames. - type = 0x04 - - stream_association = _STREAM_ASSOC_NO_STREAM - - # We need to define the known settings, they may as well be class - # attributes. - #: The byte that signals the SETTINGS_HEADER_TABLE_SIZE setting. - HEADER_TABLE_SIZE = 0x01 - #: The byte that signals the SETTINGS_ENABLE_PUSH setting. - ENABLE_PUSH = 0x02 - #: The byte that signals the SETTINGS_MAX_CONCURRENT_STREAMS setting. - MAX_CONCURRENT_STREAMS = 0x03 - #: The byte that signals the SETTINGS_INITIAL_WINDOW_SIZE setting. - INITIAL_WINDOW_SIZE = 0x04 - #: The byte that signals the SETTINGS_MAX_FRAME_SIZE setting. - MAX_FRAME_SIZE = 0x05 - #: The byte that signals the SETTINGS_MAX_HEADER_LIST_SIZE setting. - MAX_HEADER_LIST_SIZE = 0x06 - #: The byte that signals SETTINGS_ENABLE_CONNECT_PROTOCOL setting. - ENABLE_CONNECT_PROTOCOL = 0x08 - - def __init__(self, stream_id: int = 0, settings: dict[int, int] | None = None, **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - if settings and "ACK" in kwargs.get("flags", ()): - msg = "Settings must be empty if ACK flag is set." - raise InvalidDataError(msg) - - #: A dictionary of the setting type byte to the value of the setting. - self.settings: dict[int, int] = settings or {} - - def _body_repr(self) -> str: - return f"settings={self.settings}" - - def serialize_body(self) -> bytes: - return b"".join([_STRUCT_HL.pack(setting & 0xFF, value) - for setting, value in self.settings.items()]) - - def parse_body(self, data: memoryview) -> None: - if "ACK" in self.flags and len(data) > 0: - msg = f"SETTINGS ack frame must not have payload: got {len(data)} bytes" - raise InvalidDataError(msg) - - body_len = 0 - for i in range(0, len(data), 6): - try: - name, value = _STRUCT_HL.unpack(data[i:i+6]) - except struct.error as err: - msg = "Invalid SETTINGS body" - raise InvalidFrameError(msg) from err - - self.settings[name] = value - body_len += 6 - - self.body_len = body_len - - -class PushPromiseFrame(Padding, Frame): - """ - The PUSH_PROMISE frame is used to notify the peer endpoint in advance of - streams the sender intends to initiate. - """ - - #: The flags defined for PUSH_PROMISE frames. - defined_flags = [ - Flag("END_HEADERS", 0x04), - Flag("PADDED", 0x08), - ] - - #: The type byte defined for PUSH_PROMISE frames. - type = 0x05 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id: int, promised_stream_id: int = 0, data: bytes = b"", **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The stream ID that is promised by this frame. - self.promised_stream_id = promised_stream_id - - #: The HPACK-encoded header block for the simulated request on the new - #: stream. - self.data = data - - def _body_repr(self) -> str: - return f"promised_stream_id={self.promised_stream_id}, data={_raw_data_repr(self.data)}" - - def serialize_body(self) -> bytes: - padding_data = self.serialize_padding_data() - padding = b"\0" * self.pad_length - data = _STRUCT_L.pack(self.promised_stream_id) - return b"".join([padding_data, data, self.data, padding]) - - def parse_body(self, data: memoryview) -> None: - padding_data_length = self.parse_padding_data(data) - - try: - self.promised_stream_id = _STRUCT_L.unpack( - data[padding_data_length:padding_data_length + 4], - )[0] - except struct.error as err: - msg = "Invalid PUSH_PROMISE body" - raise InvalidFrameError(msg) from err - - self.data = ( - data[padding_data_length + 4:len(data)-self.pad_length].tobytes() - ) - self.body_len = len(data) - - if self.promised_stream_id == 0 or self.promised_stream_id % 2 != 0: - msg = f"Invalid PUSH_PROMISE promised stream id: {self.promised_stream_id}" - raise InvalidDataError(msg) - - if self.pad_length and self.pad_length >= self.body_len: - msg = "Padding is too long." - raise InvalidPaddingError(msg) - - -class PingFrame(Frame): - """ - The PING frame is a mechanism for measuring a minimal round-trip time from - the sender, as well as determining whether an idle connection is still - functional. PING frames can be sent from any endpoint. - """ - - #: The flags defined for PING frames. - defined_flags = [Flag("ACK", 0x01)] - - #: The type byte defined for PING frames. - type = 0x06 - - stream_association = _STREAM_ASSOC_NO_STREAM - - def __init__(self, stream_id: int = 0, opaque_data: bytes = b"", **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The opaque data sent in this PING frame, as a bytestring. - self.opaque_data = opaque_data - - def _body_repr(self) -> str: - return f"opaque_data={self.opaque_data!r}" - - def serialize_body(self) -> bytes: - if len(self.opaque_data) > 8: - msg = f"PING frame may not have more than 8 bytes of data, got {len(self.opaque_data)}" - raise InvalidFrameError(msg) - - data = self.opaque_data - data += b"\x00" * (8 - len(self.opaque_data)) - return data - - def parse_body(self, data: memoryview) -> None: - if len(data) != 8: - msg = f"PING frame must have 8 byte length: got {len(data)}" - raise InvalidFrameError(msg) - - self.opaque_data = data.tobytes() - self.body_len = 8 - - -class GoAwayFrame(Frame): - """ - The GOAWAY frame informs the remote peer to stop creating streams on this - connection. It can be sent from the client or the server. Once sent, the - sender will ignore frames sent on new streams for the remainder of the - connection. - """ - - #: The flags defined for GOAWAY frames. - defined_flags: list[Flag] = [] - - #: The type byte defined for GOAWAY frames. - type = 0x07 - - stream_association = _STREAM_ASSOC_NO_STREAM - - def __init__(self, - stream_id: int = 0, - last_stream_id: int = 0, - error_code: int = 0, - additional_data: bytes = b"", - **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The last stream ID definitely seen by the remote peer. - self.last_stream_id = last_stream_id - - #: The error code for connection teardown. - self.error_code = error_code - - #: Any additional data sent in the GOAWAY. - self.additional_data = additional_data - - def _body_repr(self) -> str: - return f"last_stream_id={self.last_stream_id}, error_code={self.error_code}, additional_data={self.additional_data!r}" - - def serialize_body(self) -> bytes: - data = _STRUCT_LL.pack( - self.last_stream_id & 0x7FFFFFFF, - self.error_code, - ) - data += self.additional_data - - return data - - def parse_body(self, data: memoryview) -> None: - try: - self.last_stream_id, self.error_code = _STRUCT_LL.unpack( - data[:8], - ) - except struct.error as err: - msg = "Invalid GOAWAY body." - raise InvalidFrameError(msg) from err - - self.body_len = len(data) - - if len(data) > 8: - self.additional_data = data[8:].tobytes() - - -class WindowUpdateFrame(Frame): - """ - The WINDOW_UPDATE frame is used to implement flow control. - - Flow control operates at two levels: on each individual stream and on the - entire connection. - - Both types of flow control are hop by hop; that is, only between the two - endpoints. Intermediaries do not forward WINDOW_UPDATE frames between - dependent connections. However, throttling of data transfer by any receiver - can indirectly cause the propagation of flow control information toward the - original sender. - """ - - #: The flags defined for WINDOW_UPDATE frames. - defined_flags: list[Flag] = [] - - #: The type byte defined for WINDOW_UPDATE frames. - type = 0x08 - - stream_association = _STREAM_ASSOC_EITHER - - def __init__(self, stream_id: int, window_increment: int = 0, **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The amount the flow control window is to be incremented. - self.window_increment = window_increment - - def _body_repr(self) -> str: - return f"window_increment={self.window_increment}" - - def serialize_body(self) -> bytes: - return _STRUCT_L.pack(self.window_increment & 0x7FFFFFFF) - - def parse_body(self, data: memoryview) -> None: - if len(data) > 4: - msg = f"WINDOW_UPDATE frame must have 4 byte length: got {len(data)}" - raise InvalidFrameError(msg) - - try: - self.window_increment = _STRUCT_L.unpack(data)[0] - except struct.error as err: - msg = "Invalid WINDOW_UPDATE body" - raise InvalidFrameError(msg) from err - - if not 1 <= self.window_increment <= 2**31-1: - msg = "WINDOW_UPDATE increment must be between 1 to 2^31-1" - raise InvalidDataError(msg) - - self.body_len = 4 - - -class HeadersFrame(Padding, Priority, Frame): - """ - The HEADERS frame carries name-value pairs. It is used to open a stream. - HEADERS frames can be sent on a stream in the "open" or "half closed - (remote)" states. - - The HeadersFrame class is actually basically a data frame in this - implementation, because of the requirement to control the sizes of frames. - A header block fragment that doesn't fit in an entire HEADERS frame needs - to be followed with CONTINUATION frames. From the perspective of the frame - building code the header block is an opaque data segment. - """ - - #: The flags defined for HEADERS frames. - defined_flags = [ - Flag("END_STREAM", 0x01), - Flag("END_HEADERS", 0x04), - Flag("PADDED", 0x08), - Flag("PRIORITY", 0x20), - ] - - #: The type byte defined for HEADERS frames. - type = 0x01 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id: int, data: bytes = b"", **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The HPACK-encoded header block. - self.data = data - - def _body_repr(self) -> str: - return f"exclusive={self.exclusive}, depends_on={self.depends_on}, stream_weight={self.stream_weight}, data={_raw_data_repr(self.data)}" - - def serialize_body(self) -> bytes: - padding_data = self.serialize_padding_data() - padding = b"\0" * self.pad_length - - if "PRIORITY" in self.flags: - priority_data = self.serialize_priority_data() - else: - priority_data = b"" - - return b"".join([padding_data, priority_data, self.data, padding]) - - def parse_body(self, data: memoryview) -> None: - padding_data_length = self.parse_padding_data(data) - data = data[padding_data_length:] - - if "PRIORITY" in self.flags: - priority_data_length = self.parse_priority_data(data) - else: - priority_data_length = 0 - - self.body_len = len(data) - self.data = ( - data[priority_data_length:len(data)-self.pad_length].tobytes() - ) - - if self.pad_length and self.pad_length >= self.body_len: - msg = "Padding is too long." - raise InvalidPaddingError(msg) - - -class ContinuationFrame(Frame): - """ - The CONTINUATION frame is used to continue a sequence of header block - fragments. Any number of CONTINUATION frames can be sent on an existing - stream, as long as the preceding frame on the same stream is one of - HEADERS, PUSH_PROMISE or CONTINUATION without the END_HEADERS flag set. - - Much like the HEADERS frame, hyper treats this as an opaque data frame with - different flags and a different type. - """ - - #: The flags defined for CONTINUATION frames. - defined_flags = [Flag("END_HEADERS", 0x04)] - - #: The type byte defined for CONTINUATION frames. - type = 0x09 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id: int, data: bytes = b"", **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - #: The HPACK-encoded header block. - self.data = data - - def _body_repr(self) -> str: - return f"data={_raw_data_repr(self.data)}" - - def serialize_body(self) -> bytes: - return self.data - - def parse_body(self, data: memoryview) -> None: - self.data = data.tobytes() - self.body_len = len(data) - - -class AltSvcFrame(Frame): - """ - The ALTSVC frame is used to advertise alternate services that the current - host, or a different one, can understand. This frame is standardised as - part of RFC 7838. - - This frame does no work to validate that the ALTSVC field parameter is - acceptable per the rules of RFC 7838. - - .. note:: If the ``stream_id`` of this frame is nonzero, the origin field - must have zero length. Conversely, if the ``stream_id`` of this - frame is zero, the origin field must have nonzero length. Put - another way, a valid ALTSVC frame has ``stream_id != 0`` XOR - ``len(origin) != 0``. - """ - - type = 0x0A - - stream_association = _STREAM_ASSOC_EITHER - - def __init__(self, stream_id: int, origin: bytes = b"", field: bytes = b"", **kwargs: Any) -> None: - super().__init__(stream_id, **kwargs) - - if not isinstance(origin, bytes): - msg = "AltSvc origin must be a bytestring." - raise InvalidDataError(msg) - if not isinstance(field, bytes): - msg = "AltSvc field must be a bytestring." - raise InvalidDataError(msg) - self.origin = origin - self.field = field - - def _body_repr(self) -> str: - return f"origin={self.origin!r}, field={self.field!r}" - - def serialize_body(self) -> bytes: - origin_len = _STRUCT_H.pack(len(self.origin)) - return b"".join([origin_len, self.origin, self.field]) - - def parse_body(self, data: memoryview) -> None: - try: - origin_len = _STRUCT_H.unpack(data[0:2])[0] - self.origin = data[2:2+origin_len].tobytes() - - if len(self.origin) != origin_len: - msg = "Invalid ALTSVC frame body." - raise InvalidFrameError(msg) - - self.field = data[2+origin_len:].tobytes() - except (struct.error, ValueError) as err: - msg = "Invalid ALTSVC frame body." - raise InvalidFrameError(msg) from err - - self.body_len = len(data) - - -class ExtensionFrame(Frame): - """ - ExtensionFrame is used to wrap frames which are not natively interpretable - by hyperframe. - - Although certain byte prefixes are ordained by specification to have - certain contextual meanings, frames with other prefixes are not prohibited, - and may be used to communicate arbitrary meaning between HTTP/2 peers. - - Thus, hyperframe, rather than raising an exception when such a frame is - encountered, wraps it in a generic frame to be properly acted upon by - upstream consumers which might have additional context on how to use it. - - .. versionadded:: 5.0.0 - """ - - stream_association = _STREAM_ASSOC_EITHER - - def __init__(self, type: int, stream_id: int, flag_byte: int = 0x0, body: bytes = b"", **kwargs: Any) -> None: # noqa: A002 - super().__init__(stream_id, **kwargs) - self.type = type - self.flag_byte = flag_byte - self.body = body - - def _body_repr(self) -> str: - return f"type={self.type}, flag_byte={self.flag_byte}, body={_raw_data_repr(self.body)}" - - def parse_flags(self, flag_byte: int) -> None: # type: ignore - """ - For extension frames, we parse the flags by just storing a flag byte. - """ - self.flag_byte = flag_byte - - def parse_body(self, data: memoryview) -> None: - self.body = data.tobytes() - self.body_len = len(data) - - def serialize(self) -> bytes: - """ - A broad override of the serialize method that ensures that the data - comes back out exactly as it came in. This should not be used in most - user code: it exists only as a helper method if frames need to be - reconstituted. - """ - # Build the frame header. - # First, get the flags. - flags = self.flag_byte - - header = _STRUCT_HBBBL.pack( - (self.body_len >> 8) & 0xFFFF, # Length spread over top 24 bits - self.body_len & 0xFF, - self.type, - flags, - self.stream_id & 0x7FFFFFFF, # Stream ID is 32 bits. - ) - - return header + self.body - - -def _raw_data_repr(data: bytes | None) -> str: - if not data: - return "None" - r = binascii.hexlify(data).decode("ascii") - if len(r) > 20: - r = r[:20] + "..." - return "" - - -_FRAME_CLASSES: list[type[Frame]] = [ - DataFrame, - HeadersFrame, - PriorityFrame, - RstStreamFrame, - SettingsFrame, - PushPromiseFrame, - PingFrame, - GoAwayFrame, - WindowUpdateFrame, - ContinuationFrame, - AltSvcFrame, -] -#: FRAMES maps the type byte for each frame to the class used to represent that -#: frame. -FRAMES = {cls.type: cls for cls in _FRAME_CLASSES} diff --git a/serverenv/lib/python3.9/site-packages/hyperframe/py.typed b/serverenv/lib/python3.9/site-packages/hyperframe/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/METADATA deleted file mode 100644 index 5dbad86..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/METADATA +++ /dev/null @@ -1,134 +0,0 @@ -Metadata-Version: 2.4 -Name: importlib_metadata -Version: 8.7.0 -Summary: Read metadata from Python packages -Author-email: "Jason R. Coombs" -Project-URL: Source, https://github.com/python/importlib_metadata -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Requires-Python: >=3.9 -Description-Content-Type: text/x-rst -License-File: LICENSE -Requires-Dist: zipp>=3.20 -Requires-Dist: typing-extensions>=3.6.4; python_version < "3.8" -Provides-Extra: test -Requires-Dist: pytest!=8.1.*,>=6; extra == "test" -Requires-Dist: importlib_resources>=1.3; python_version < "3.9" and extra == "test" -Requires-Dist: packaging; extra == "test" -Requires-Dist: pyfakefs; extra == "test" -Requires-Dist: flufl.flake8; extra == "test" -Requires-Dist: pytest-perf>=0.9.2; extra == "test" -Requires-Dist: jaraco.test>=5.4; extra == "test" -Provides-Extra: doc -Requires-Dist: sphinx>=3.5; extra == "doc" -Requires-Dist: jaraco.packaging>=9.3; extra == "doc" -Requires-Dist: rst.linker>=1.9; extra == "doc" -Requires-Dist: furo; extra == "doc" -Requires-Dist: sphinx-lint; extra == "doc" -Requires-Dist: jaraco.tidelift>=1.4; extra == "doc" -Provides-Extra: perf -Requires-Dist: ipython; extra == "perf" -Provides-Extra: check -Requires-Dist: pytest-checkdocs>=2.4; extra == "check" -Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == "check" -Provides-Extra: cover -Requires-Dist: pytest-cov; extra == "cover" -Provides-Extra: enabler -Requires-Dist: pytest-enabler>=2.2; extra == "enabler" -Provides-Extra: type -Requires-Dist: pytest-mypy; extra == "type" -Dynamic: license-file - -.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg - :target: https://pypi.org/project/importlib_metadata - -.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg - -.. image:: https://github.com/python/importlib_metadata/actions/workflows/main.yml/badge.svg - :target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22tests%22 - :alt: tests - -.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json - :target: https://github.com/astral-sh/ruff - :alt: Ruff - -.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest - :target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest - -.. image:: https://img.shields.io/badge/skeleton-2025-informational - :target: https://blog.jaraco.com/skeleton - -.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata - :target: https://tidelift.com/subscription/pkg/pypi-importlib-metadata?utm_source=pypi-importlib-metadata&utm_medium=readme - -Library to access the metadata for a Python package. - -This package supplies third-party access to the functionality of -`importlib.metadata `_ -including improvements added to subsequent Python versions. - - -Compatibility -============= - -New features are introduced in this third-party library and later merged -into CPython. The following table indicates which versions of this library -were contributed to different versions in the standard library: - -.. list-table:: - :header-rows: 1 - - * - importlib_metadata - - stdlib - * - 7.0 - - 3.13 - * - 6.5 - - 3.12 - * - 4.13 - - 3.11 - * - 4.6 - - 3.10 - * - 1.4 - - 3.8 - - -Usage -===== - -See the `online documentation `_ -for usage details. - -`Finder authors -`_ can -also add support for custom package installers. See the above documentation -for details. - - -Caveats -======= - -This project primarily supports third-party packages installed by PyPA -tools (or other conforming packages). It does not support: - -- Packages in the stdlib. -- Packages installed without metadata. - -Project details -=============== - - * Project home: https://github.com/python/importlib_metadata - * Report bugs at: https://github.com/python/importlib_metadata/issues - * Code hosting: https://github.com/python/importlib_metadata - * Documentation: https://importlib-metadata.readthedocs.io/ - -For Enterprise -============== - -Available as part of the Tidelift Subscription. - -This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. - -`Learn more `_. diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/RECORD deleted file mode 100644 index 38dc7d7..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/RECORD +++ /dev/null @@ -1,33 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_adapters.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_collections.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_compat.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_functools.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_itertools.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_meta.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_text.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/_typing.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py311.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py39.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/importlib_metadata/diagnose.cpython-39.pyc,, -importlib_metadata-8.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -importlib_metadata-8.7.0.dist-info/METADATA,sha256=QJMudfqWDjfobdzipgUH5gskLahdXueIgy433mjk_Qw,4760 -importlib_metadata-8.7.0.dist-info/RECORD,, -importlib_metadata-8.7.0.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91 -importlib_metadata-8.7.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358 -importlib_metadata-8.7.0.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19 -importlib_metadata/__init__.py,sha256=R60WJL9VdkZ9SgxtzCH-AU604rJPmNBnntPrUfcNEqc,37062 -importlib_metadata/_adapters.py,sha256=9Y3FAlZuoo8pOMVLnKXm5Xx6hKgsdUQOXF5SkiDGqWo,3784 -importlib_metadata/_collections.py,sha256=CxAhzlF3g1rwu_fMiB53JtRQiUFh0RgiMpoOvmK_ocg,760 -importlib_metadata/_compat.py,sha256=VC5ZDLlT-BcshauCShdFJvMNLntJJfZzNK1meGa-enw,1313 -importlib_metadata/_functools.py,sha256=bSbAqC9-2niWM9364FYBx9GWtetnJEfo4mdLv8uMl7c,2895 -importlib_metadata/_itertools.py,sha256=nMvp9SfHAQ_JYwK4L2i64lr3GRXGlYlikGTVzWbys_E,5351 -importlib_metadata/_meta.py,sha256=EtHyiJ5kGzWFDfKyQ2XQp6Vu113CeadKW1Vf6aGc1B4,1765 -importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166 -importlib_metadata/_typing.py,sha256=EQKhhsEgz_Sa-FnePI-faC72rNOOQwopjA1i5pG8FDU,367 -importlib_metadata/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -importlib_metadata/compat/py311.py,sha256=uqm-K-uohyj1042TH4a9Er_I5o7667DvulcD-gC_fSA,608 -importlib_metadata/compat/py39.py,sha256=J3W7PUVRPNYMmcvT12RF8ndBU9e8_T0Ac4U87Bsrq70,1187 -importlib_metadata/diagnose.py,sha256=nkSRMiowlmkhLYhKhvCg9glmt_11Cox-EmLzEbqYTa8,379 -importlib_metadata/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/WHEEL deleted file mode 100644 index 8acb955..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (79.0.1) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/licenses/LICENSE b/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/licenses/LICENSE deleted file mode 100644 index d645695..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - 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/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/top_level.txt b/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/top_level.txt deleted file mode 100644 index bbb0754..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata-8.7.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -importlib_metadata diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/__init__.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/__init__.py deleted file mode 100644 index cdfc1f6..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/__init__.py +++ /dev/null @@ -1,1175 +0,0 @@ -""" -APIs exposing metadata from third-party Python packages. - -This codebase is shared between importlib.metadata in the stdlib -and importlib_metadata in PyPI. See -https://github.com/python/importlib_metadata/wiki/Development-Methodology -for more detail. -""" - -from __future__ import annotations - -import abc -import collections -import email -import functools -import itertools -import operator -import os -import pathlib -import posixpath -import re -import sys -import textwrap -import types -from collections.abc import Iterable, Mapping -from contextlib import suppress -from importlib import import_module -from importlib.abc import MetaPathFinder -from itertools import starmap -from typing import Any - -from . import _meta -from ._collections import FreezableDefaultDict, Pair -from ._compat import ( - NullFinder, - install, -) -from ._functools import method_cache, pass_none -from ._itertools import always_iterable, bucket, unique_everseen -from ._meta import PackageMetadata, SimplePath -from ._typing import md_none -from .compat import py39, py311 - -__all__ = [ - 'Distribution', - 'DistributionFinder', - 'PackageMetadata', - 'PackageNotFoundError', - 'SimplePath', - 'distribution', - 'distributions', - 'entry_points', - 'files', - 'metadata', - 'packages_distributions', - 'requires', - 'version', -] - - -class PackageNotFoundError(ModuleNotFoundError): - """The package was not found.""" - - def __str__(self) -> str: - return f"No package metadata was found for {self.name}" - - @property - def name(self) -> str: # type: ignore[override] # make readonly - (name,) = self.args - return name - - -class Sectioned: - """ - A simple entry point config parser for performance - - >>> for item in Sectioned.read(Sectioned._sample): - ... print(item) - Pair(name='sec1', value='# comments ignored') - Pair(name='sec1', value='a = 1') - Pair(name='sec1', value='b = 2') - Pair(name='sec2', value='a = 2') - - >>> res = Sectioned.section_pairs(Sectioned._sample) - >>> item = next(res) - >>> item.name - 'sec1' - >>> item.value - Pair(name='a', value='1') - >>> item = next(res) - >>> item.value - Pair(name='b', value='2') - >>> item = next(res) - >>> item.name - 'sec2' - >>> item.value - Pair(name='a', value='2') - >>> list(res) - [] - """ - - _sample = textwrap.dedent( - """ - [sec1] - # comments ignored - a = 1 - b = 2 - - [sec2] - a = 2 - """ - ).lstrip() - - @classmethod - def section_pairs(cls, text): - return ( - section._replace(value=Pair.parse(section.value)) - for section in cls.read(text, filter_=cls.valid) - if section.name is not None - ) - - @staticmethod - def read(text, filter_=None): - lines = filter(filter_, map(str.strip, text.splitlines())) - name = None - for value in lines: - section_match = value.startswith('[') and value.endswith(']') - if section_match: - name = value.strip('[]') - continue - yield Pair(name, value) - - @staticmethod - def valid(line: str): - return line and not line.startswith('#') - - -class _EntryPointMatch(types.SimpleNamespace): - module: str - attr: str - extras: str - - -class EntryPoint: - """An entry point as defined by Python packaging conventions. - - See `the packaging docs on entry points - `_ - for more information. - - >>> ep = EntryPoint( - ... name=None, group=None, value='package.module:attr [extra1, extra2]') - >>> ep.module - 'package.module' - >>> ep.attr - 'attr' - >>> ep.extras - ['extra1', 'extra2'] - - If the value package or module are not valid identifiers, a - ValueError is raised on access. - - >>> EntryPoint(name=None, group=None, value='invalid-name').module - Traceback (most recent call last): - ... - ValueError: ('Invalid object reference...invalid-name... - >>> EntryPoint(name=None, group=None, value='invalid-name').attr - Traceback (most recent call last): - ... - ValueError: ('Invalid object reference...invalid-name... - >>> EntryPoint(name=None, group=None, value='invalid-name').extras - Traceback (most recent call last): - ... - ValueError: ('Invalid object reference...invalid-name... - - The same thing happens on construction. - - >>> EntryPoint(name=None, group=None, value='invalid-name') - Traceback (most recent call last): - ... - ValueError: ('Invalid object reference...invalid-name... - - """ - - pattern = re.compile( - r'(?P[\w.]+)\s*' - r'(:\s*(?P[\w.]+)\s*)?' - r'((?P\[.*\])\s*)?$' - ) - """ - A regular expression describing the syntax for an entry point, - which might look like: - - - module - - package.module - - package.module:attribute - - package.module:object.attribute - - package.module:attr [extra1, extra2] - - Other combinations are possible as well. - - The expression is lenient about whitespace around the ':', - following the attr, and following any extras. - """ - - name: str - value: str - group: str - - dist: Distribution | None = None - - def __init__(self, name: str, value: str, group: str) -> None: - vars(self).update(name=name, value=value, group=group) - self.module - - def load(self) -> Any: - """Load the entry point from its definition. If only a module - is indicated by the value, return that module. Otherwise, - return the named object. - """ - module = import_module(self.module) - attrs = filter(None, (self.attr or '').split('.')) - return functools.reduce(getattr, attrs, module) - - @property - def module(self) -> str: - return self._match.module - - @property - def attr(self) -> str: - return self._match.attr - - @property - def extras(self) -> list[str]: - return re.findall(r'\w+', self._match.extras or '') - - @functools.cached_property - def _match(self) -> _EntryPointMatch: - match = self.pattern.match(self.value) - if not match: - raise ValueError( - 'Invalid object reference. ' - 'See https://packaging.python.org' - '/en/latest/specifications/entry-points/#data-model', - self.value, - ) - return _EntryPointMatch(**match.groupdict()) - - def _for(self, dist): - vars(self).update(dist=dist) - return self - - def matches(self, **params): - """ - EntryPoint matches the given parameters. - - >>> ep = EntryPoint(group='foo', name='bar', value='bing:bong [extra1, extra2]') - >>> ep.matches(group='foo') - True - >>> ep.matches(name='bar', value='bing:bong [extra1, extra2]') - True - >>> ep.matches(group='foo', name='other') - False - >>> ep.matches() - True - >>> ep.matches(extras=['extra1', 'extra2']) - True - >>> ep.matches(module='bing') - True - >>> ep.matches(attr='bong') - True - """ - self._disallow_dist(params) - attrs = (getattr(self, param) for param in params) - return all(map(operator.eq, params.values(), attrs)) - - @staticmethod - def _disallow_dist(params): - """ - Querying by dist is not allowed (dist objects are not comparable). - >>> EntryPoint(name='fan', value='fav', group='fag').matches(dist='foo') - Traceback (most recent call last): - ... - ValueError: "dist" is not suitable for matching... - """ - if "dist" in params: - raise ValueError( - '"dist" is not suitable for matching. ' - "Instead, use Distribution.entry_points.select() on a " - "located distribution." - ) - - def _key(self): - return self.name, self.value, self.group - - def __lt__(self, other): - return self._key() < other._key() - - def __eq__(self, other): - return self._key() == other._key() - - def __setattr__(self, name, value): - raise AttributeError("EntryPoint objects are immutable.") - - def __repr__(self): - return ( - f'EntryPoint(name={self.name!r}, value={self.value!r}, ' - f'group={self.group!r})' - ) - - def __hash__(self) -> int: - return hash(self._key()) - - -class EntryPoints(tuple): - """ - An immutable collection of selectable EntryPoint objects. - """ - - __slots__ = () - - def __getitem__(self, name: str) -> EntryPoint: # type: ignore[override] # Work with str instead of int - """ - Get the EntryPoint in self matching name. - """ - try: - return next(iter(self.select(name=name))) - except StopIteration: - raise KeyError(name) - - def __repr__(self): - """ - Repr with classname and tuple constructor to - signal that we deviate from regular tuple behavior. - """ - return '%s(%r)' % (self.__class__.__name__, tuple(self)) - - def select(self, **params) -> EntryPoints: - """ - Select entry points from self that match the - given parameters (typically group and/or name). - """ - return EntryPoints(ep for ep in self if py39.ep_matches(ep, **params)) - - @property - def names(self) -> set[str]: - """ - Return the set of all names of all entry points. - """ - return {ep.name for ep in self} - - @property - def groups(self) -> set[str]: - """ - Return the set of all groups of all entry points. - """ - return {ep.group for ep in self} - - @classmethod - def _from_text_for(cls, text, dist): - return cls(ep._for(dist) for ep in cls._from_text(text)) - - @staticmethod - def _from_text(text): - return ( - EntryPoint(name=item.value.name, value=item.value.value, group=item.name) - for item in Sectioned.section_pairs(text or '') - ) - - -class PackagePath(pathlib.PurePosixPath): - """A reference to a path in a package""" - - hash: FileHash | None - size: int - dist: Distribution - - def read_text(self, encoding: str = 'utf-8') -> str: - return self.locate().read_text(encoding=encoding) - - def read_binary(self) -> bytes: - return self.locate().read_bytes() - - def locate(self) -> SimplePath: - """Return a path-like object for this path""" - return self.dist.locate_file(self) - - -class FileHash: - def __init__(self, spec: str) -> None: - self.mode, _, self.value = spec.partition('=') - - def __repr__(self) -> str: - return f'' - - -class Distribution(metaclass=abc.ABCMeta): - """ - An abstract Python distribution package. - - Custom providers may derive from this class and define - the abstract methods to provide a concrete implementation - for their environment. Some providers may opt to override - the default implementation of some properties to bypass - the file-reading mechanism. - """ - - @abc.abstractmethod - def read_text(self, filename) -> str | None: - """Attempt to load metadata file given by the name. - - Python distribution metadata is organized by blobs of text - typically represented as "files" in the metadata directory - (e.g. package-1.0.dist-info). These files include things - like: - - - METADATA: The distribution metadata including fields - like Name and Version and Description. - - entry_points.txt: A series of entry points as defined in - `the entry points spec `_. - - RECORD: A record of files according to - `this recording spec `_. - - A package may provide any set of files, including those - not listed here or none at all. - - :param filename: The name of the file in the distribution info. - :return: The text if found, otherwise None. - """ - - @abc.abstractmethod - def locate_file(self, path: str | os.PathLike[str]) -> SimplePath: - """ - Given a path to a file in this distribution, return a SimplePath - to it. - - This method is used by callers of ``Distribution.files()`` to - locate files within the distribution. If it's possible for a - Distribution to represent files in the distribution as - ``SimplePath`` objects, it should implement this method - to resolve such objects. - - Some Distribution providers may elect not to resolve SimplePath - objects within the distribution by raising a - NotImplementedError, but consumers of such a Distribution would - be unable to invoke ``Distribution.files()``. - """ - - @classmethod - def from_name(cls, name: str) -> Distribution: - """Return the Distribution for the given package name. - - :param name: The name of the distribution package to search for. - :return: The Distribution instance (or subclass thereof) for the named - package, if found. - :raises PackageNotFoundError: When the named package's distribution - metadata cannot be found. - :raises ValueError: When an invalid value is supplied for name. - """ - if not name: - raise ValueError("A distribution name is required.") - try: - return next(iter(cls._prefer_valid(cls.discover(name=name)))) - except StopIteration: - raise PackageNotFoundError(name) - - @classmethod - def discover( - cls, *, context: DistributionFinder.Context | None = None, **kwargs - ) -> Iterable[Distribution]: - """Return an iterable of Distribution objects for all packages. - - Pass a ``context`` or pass keyword arguments for constructing - a context. - - :context: A ``DistributionFinder.Context`` object. - :return: Iterable of Distribution objects for packages matching - the context. - """ - if context and kwargs: - raise ValueError("cannot accept context and kwargs") - context = context or DistributionFinder.Context(**kwargs) - return itertools.chain.from_iterable( - resolver(context) for resolver in cls._discover_resolvers() - ) - - @staticmethod - def _prefer_valid(dists: Iterable[Distribution]) -> Iterable[Distribution]: - """ - Prefer (move to the front) distributions that have metadata. - - Ref python/importlib_resources#489. - """ - buckets = bucket(dists, lambda dist: bool(dist.metadata)) - return itertools.chain(buckets[True], buckets[False]) - - @staticmethod - def at(path: str | os.PathLike[str]) -> Distribution: - """Return a Distribution for the indicated metadata path. - - :param path: a string or path-like object - :return: a concrete Distribution instance for the path - """ - return PathDistribution(pathlib.Path(path)) - - @staticmethod - def _discover_resolvers(): - """Search the meta_path for resolvers (MetadataPathFinders).""" - declared = ( - getattr(finder, 'find_distributions', None) for finder in sys.meta_path - ) - return filter(None, declared) - - @property - def metadata(self) -> _meta.PackageMetadata | None: - """Return the parsed metadata for this Distribution. - - The returned object will have keys that name the various bits of - metadata per the - `Core metadata specifications `_. - - Custom providers may provide the METADATA file or override this - property. - """ - - text = ( - self.read_text('METADATA') - or self.read_text('PKG-INFO') - # This last clause is here to support old egg-info files. Its - # effect is to just end up using the PathDistribution's self._path - # (which points to the egg-info file) attribute unchanged. - or self.read_text('') - ) - return self._assemble_message(text) - - @staticmethod - @pass_none - def _assemble_message(text: str) -> _meta.PackageMetadata: - # deferred for performance (python/cpython#109829) - from . import _adapters - - return _adapters.Message(email.message_from_string(text)) - - @property - def name(self) -> str: - """Return the 'Name' metadata for the distribution package.""" - return md_none(self.metadata)['Name'] - - @property - def _normalized_name(self): - """Return a normalized version of the name.""" - return Prepared.normalize(self.name) - - @property - def version(self) -> str: - """Return the 'Version' metadata for the distribution package.""" - return md_none(self.metadata)['Version'] - - @property - def entry_points(self) -> EntryPoints: - """ - Return EntryPoints for this distribution. - - Custom providers may provide the ``entry_points.txt`` file - or override this property. - """ - return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self) - - @property - def files(self) -> list[PackagePath] | None: - """Files in this distribution. - - :return: List of PackagePath for this distribution or None - - Result is `None` if the metadata file that enumerates files - (i.e. RECORD for dist-info, or installed-files.txt or - SOURCES.txt for egg-info) is missing. - Result may be empty if the metadata exists but is empty. - - Custom providers are recommended to provide a "RECORD" file (in - ``read_text``) or override this property to allow for callers to be - able to resolve filenames provided by the package. - """ - - def make_file(name, hash=None, size_str=None): - result = PackagePath(name) - result.hash = FileHash(hash) if hash else None - result.size = int(size_str) if size_str else None - result.dist = self - return result - - @pass_none - def make_files(lines): - # Delay csv import, since Distribution.files is not as widely used - # as other parts of importlib.metadata - import csv - - return starmap(make_file, csv.reader(lines)) - - @pass_none - def skip_missing_files(package_paths): - return list(filter(lambda path: path.locate().exists(), package_paths)) - - return skip_missing_files( - make_files( - self._read_files_distinfo() - or self._read_files_egginfo_installed() - or self._read_files_egginfo_sources() - ) - ) - - def _read_files_distinfo(self): - """ - Read the lines of RECORD. - """ - text = self.read_text('RECORD') - return text and text.splitlines() - - def _read_files_egginfo_installed(self): - """ - Read installed-files.txt and return lines in a similar - CSV-parsable format as RECORD: each file must be placed - relative to the site-packages directory and must also be - quoted (since file names can contain literal commas). - - This file is written when the package is installed by pip, - but it might not be written for other installation methods. - Assume the file is accurate if it exists. - """ - text = self.read_text('installed-files.txt') - # Prepend the .egg-info/ subdir to the lines in this file. - # But this subdir is only available from PathDistribution's - # self._path. - subdir = getattr(self, '_path', None) - if not text or not subdir: - return - - paths = ( - py311.relative_fix((subdir / name).resolve()) - .relative_to(self.locate_file('').resolve(), walk_up=True) - .as_posix() - for name in text.splitlines() - ) - return map('"{}"'.format, paths) - - def _read_files_egginfo_sources(self): - """ - Read SOURCES.txt and return lines in a similar CSV-parsable - format as RECORD: each file name must be quoted (since it - might contain literal commas). - - Note that SOURCES.txt is not a reliable source for what - files are installed by a package. This file is generated - for a source archive, and the files that are present - there (e.g. setup.py) may not correctly reflect the files - that are present after the package has been installed. - """ - text = self.read_text('SOURCES.txt') - return text and map('"{}"'.format, text.splitlines()) - - @property - def requires(self) -> list[str] | None: - """Generated requirements specified for this Distribution""" - reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs() - return reqs and list(reqs) - - def _read_dist_info_reqs(self): - return self.metadata.get_all('Requires-Dist') - - def _read_egg_info_reqs(self): - source = self.read_text('requires.txt') - return pass_none(self._deps_from_requires_text)(source) - - @classmethod - def _deps_from_requires_text(cls, source): - return cls._convert_egg_info_reqs_to_simple_reqs(Sectioned.read(source)) - - @staticmethod - def _convert_egg_info_reqs_to_simple_reqs(sections): - """ - Historically, setuptools would solicit and store 'extra' - requirements, including those with environment markers, - in separate sections. More modern tools expect each - dependency to be defined separately, with any relevant - extras and environment markers attached directly to that - requirement. This method converts the former to the - latter. See _test_deps_from_requires_text for an example. - """ - - def make_condition(name): - return name and f'extra == "{name}"' - - def quoted_marker(section): - section = section or '' - extra, sep, markers = section.partition(':') - if extra and markers: - markers = f'({markers})' - conditions = list(filter(None, [markers, make_condition(extra)])) - return '; ' + ' and '.join(conditions) if conditions else '' - - def url_req_space(req): - """ - PEP 508 requires a space between the url_spec and the quoted_marker. - Ref python/importlib_metadata#357. - """ - # '@' is uniquely indicative of a url_req. - return ' ' * ('@' in req) - - for section in sections: - space = url_req_space(section.value) - yield section.value + space + quoted_marker(section.name) - - @property - def origin(self): - return self._load_json('direct_url.json') - - def _load_json(self, filename): - # Deferred for performance (python/importlib_metadata#503) - import json - - return pass_none(json.loads)( - self.read_text(filename), - object_hook=lambda data: types.SimpleNamespace(**data), - ) - - -class DistributionFinder(MetaPathFinder): - """ - A MetaPathFinder capable of discovering installed distributions. - - Custom providers should implement this interface in order to - supply metadata. - """ - - class Context: - """ - Keyword arguments presented by the caller to - ``distributions()`` or ``Distribution.discover()`` - to narrow the scope of a search for distributions - in all DistributionFinders. - - Each DistributionFinder may expect any parameters - and should attempt to honor the canonical - parameters defined below when appropriate. - - This mechanism gives a custom provider a means to - solicit additional details from the caller beyond - "name" and "path" when searching distributions. - For example, imagine a provider that exposes suites - of packages in either a "public" or "private" ``realm``. - A caller may wish to query only for distributions in - a particular realm and could call - ``distributions(realm="private")`` to signal to the - custom provider to only include distributions from that - realm. - """ - - name = None - """ - Specific name for which a distribution finder should match. - A name of ``None`` matches all distributions. - """ - - def __init__(self, **kwargs): - vars(self).update(kwargs) - - @property - def path(self) -> list[str]: - """ - The sequence of directory path that a distribution finder - should search. - - Typically refers to Python installed package paths such as - "site-packages" directories and defaults to ``sys.path``. - """ - return vars(self).get('path', sys.path) - - @abc.abstractmethod - def find_distributions(self, context=Context()) -> Iterable[Distribution]: - """ - Find distributions. - - Return an iterable of all Distribution instances capable of - loading the metadata for packages matching the ``context``, - a DistributionFinder.Context instance. - """ - - -class FastPath: - """ - Micro-optimized class for searching a root for children. - - Root is a path on the file system that may contain metadata - directories either as natural directories or within a zip file. - - >>> FastPath('').children() - ['...'] - - FastPath objects are cached and recycled for any given root. - - >>> FastPath('foobar') is FastPath('foobar') - True - """ - - @functools.lru_cache() # type: ignore[misc] - def __new__(cls, root): - return super().__new__(cls) - - def __init__(self, root): - self.root = root - - def joinpath(self, child): - return pathlib.Path(self.root, child) - - def children(self): - with suppress(Exception): - return os.listdir(self.root or '.') - with suppress(Exception): - return self.zip_children() - return [] - - def zip_children(self): - # deferred for performance (python/importlib_metadata#502) - from zipp.compat.overlay import zipfile - - zip_path = zipfile.Path(self.root) - names = zip_path.root.namelist() - self.joinpath = zip_path.joinpath - - return dict.fromkeys(child.split(posixpath.sep, 1)[0] for child in names) - - def search(self, name): - return self.lookup(self.mtime).search(name) - - @property - def mtime(self): - with suppress(OSError): - return os.stat(self.root).st_mtime - self.lookup.cache_clear() - - @method_cache - def lookup(self, mtime): - return Lookup(self) - - -class Lookup: - """ - A micro-optimized class for searching a (fast) path for metadata. - """ - - def __init__(self, path: FastPath): - """ - Calculate all of the children representing metadata. - - From the children in the path, calculate early all of the - children that appear to represent metadata (infos) or legacy - metadata (eggs). - """ - - base = os.path.basename(path.root).lower() - base_is_egg = base.endswith(".egg") - self.infos = FreezableDefaultDict(list) - self.eggs = FreezableDefaultDict(list) - - for child in path.children(): - low = child.lower() - if low.endswith((".dist-info", ".egg-info")): - # rpartition is faster than splitext and suitable for this purpose. - name = low.rpartition(".")[0].partition("-")[0] - normalized = Prepared.normalize(name) - self.infos[normalized].append(path.joinpath(child)) - elif base_is_egg and low == "egg-info": - name = base.rpartition(".")[0].partition("-")[0] - legacy_normalized = Prepared.legacy_normalize(name) - self.eggs[legacy_normalized].append(path.joinpath(child)) - - self.infos.freeze() - self.eggs.freeze() - - def search(self, prepared: Prepared): - """ - Yield all infos and eggs matching the Prepared query. - """ - infos = ( - self.infos[prepared.normalized] - if prepared - else itertools.chain.from_iterable(self.infos.values()) - ) - eggs = ( - self.eggs[prepared.legacy_normalized] - if prepared - else itertools.chain.from_iterable(self.eggs.values()) - ) - return itertools.chain(infos, eggs) - - -class Prepared: - """ - A prepared search query for metadata on a possibly-named package. - - Pre-calculates the normalization to prevent repeated operations. - - >>> none = Prepared(None) - >>> none.normalized - >>> none.legacy_normalized - >>> bool(none) - False - >>> sample = Prepared('Sample__Pkg-name.foo') - >>> sample.normalized - 'sample_pkg_name_foo' - >>> sample.legacy_normalized - 'sample__pkg_name.foo' - >>> bool(sample) - True - """ - - normalized = None - legacy_normalized = None - - def __init__(self, name: str | None): - self.name = name - if name is None: - return - self.normalized = self.normalize(name) - self.legacy_normalized = self.legacy_normalize(name) - - @staticmethod - def normalize(name): - """ - PEP 503 normalization plus dashes as underscores. - """ - return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_') - - @staticmethod - def legacy_normalize(name): - """ - Normalize the package name as found in the convention in - older packaging tools versions and specs. - """ - return name.lower().replace('-', '_') - - def __bool__(self): - return bool(self.name) - - -@install -class MetadataPathFinder(NullFinder, DistributionFinder): - """A degenerate finder for distribution packages on the file system. - - This finder supplies only a find_distributions() method for versions - of Python that do not have a PathFinder find_distributions(). - """ - - @classmethod - def find_distributions( - cls, context=DistributionFinder.Context() - ) -> Iterable[PathDistribution]: - """ - Find distributions. - - Return an iterable of all Distribution instances capable of - loading the metadata for packages matching ``context.name`` - (or all names if ``None`` indicated) along the paths in the list - of directories ``context.path``. - """ - found = cls._search_paths(context.name, context.path) - return map(PathDistribution, found) - - @classmethod - def _search_paths(cls, name, paths): - """Find metadata directories in paths heuristically.""" - prepared = Prepared(name) - return itertools.chain.from_iterable( - path.search(prepared) for path in map(FastPath, paths) - ) - - @classmethod - def invalidate_caches(cls) -> None: - FastPath.__new__.cache_clear() - - -class PathDistribution(Distribution): - def __init__(self, path: SimplePath) -> None: - """Construct a distribution. - - :param path: SimplePath indicating the metadata directory. - """ - self._path = path - - def read_text(self, filename: str | os.PathLike[str]) -> str | None: - with suppress( - FileNotFoundError, - IsADirectoryError, - KeyError, - NotADirectoryError, - PermissionError, - ): - return self._path.joinpath(filename).read_text(encoding='utf-8') - - return None - - read_text.__doc__ = Distribution.read_text.__doc__ - - def locate_file(self, path: str | os.PathLike[str]) -> SimplePath: - return self._path.parent / path - - @property - def _normalized_name(self): - """ - Performance optimization: where possible, resolve the - normalized name from the file system path. - """ - stem = os.path.basename(str(self._path)) - return ( - pass_none(Prepared.normalize)(self._name_from_stem(stem)) - or super()._normalized_name - ) - - @staticmethod - def _name_from_stem(stem): - """ - >>> PathDistribution._name_from_stem('foo-3.0.egg-info') - 'foo' - >>> PathDistribution._name_from_stem('CherryPy-3.0.dist-info') - 'CherryPy' - >>> PathDistribution._name_from_stem('face.egg-info') - 'face' - >>> PathDistribution._name_from_stem('foo.bar') - """ - filename, ext = os.path.splitext(stem) - if ext not in ('.dist-info', '.egg-info'): - return - name, sep, rest = filename.partition('-') - return name - - -def distribution(distribution_name: str) -> Distribution: - """Get the ``Distribution`` instance for the named package. - - :param distribution_name: The name of the distribution package as a string. - :return: A ``Distribution`` instance (or subclass thereof). - """ - return Distribution.from_name(distribution_name) - - -def distributions(**kwargs) -> Iterable[Distribution]: - """Get all ``Distribution`` instances in the current environment. - - :return: An iterable of ``Distribution`` instances. - """ - return Distribution.discover(**kwargs) - - -def metadata(distribution_name: str) -> _meta.PackageMetadata | None: - """Get the metadata for the named package. - - :param distribution_name: The name of the distribution package to query. - :return: A PackageMetadata containing the parsed metadata. - """ - return Distribution.from_name(distribution_name).metadata - - -def version(distribution_name: str) -> str: - """Get the version string for the named package. - - :param distribution_name: The name of the distribution package to query. - :return: The version string for the package as defined in the package's - "Version" metadata key. - """ - return distribution(distribution_name).version - - -_unique = functools.partial( - unique_everseen, - key=py39.normalized_name, -) -""" -Wrapper for ``distributions`` to return unique distributions by name. -""" - - -def entry_points(**params) -> EntryPoints: - """Return EntryPoint objects for all installed packages. - - Pass selection parameters (group or name) to filter the - result to entry points matching those properties (see - EntryPoints.select()). - - :return: EntryPoints for all installed packages. - """ - eps = itertools.chain.from_iterable( - dist.entry_points for dist in _unique(distributions()) - ) - return EntryPoints(eps).select(**params) - - -def files(distribution_name: str) -> list[PackagePath] | None: - """Return a list of files for the named package. - - :param distribution_name: The name of the distribution package to query. - :return: List of files composing the distribution. - """ - return distribution(distribution_name).files - - -def requires(distribution_name: str) -> list[str] | None: - """ - Return a list of requirements for the named package. - - :return: An iterable of requirements, suitable for - packaging.requirement.Requirement. - """ - return distribution(distribution_name).requires - - -def packages_distributions() -> Mapping[str, list[str]]: - """ - Return a mapping of top-level packages to their - distributions. - - >>> import collections.abc - >>> pkgs = packages_distributions() - >>> all(isinstance(dist, collections.abc.Sequence) for dist in pkgs.values()) - True - """ - pkg_to_dist = collections.defaultdict(list) - for dist in distributions(): - for pkg in _top_level_declared(dist) or _top_level_inferred(dist): - pkg_to_dist[pkg].append(md_none(dist.metadata)['Name']) - return dict(pkg_to_dist) - - -def _top_level_declared(dist): - return (dist.read_text('top_level.txt') or '').split() - - -def _topmost(name: PackagePath) -> str | None: - """ - Return the top-most parent as long as there is a parent. - """ - top, *rest = name.parts - return top if rest else None - - -def _get_toplevel_name(name: PackagePath) -> str: - """ - Infer a possibly importable module name from a name presumed on - sys.path. - - >>> _get_toplevel_name(PackagePath('foo.py')) - 'foo' - >>> _get_toplevel_name(PackagePath('foo')) - 'foo' - >>> _get_toplevel_name(PackagePath('foo.pyc')) - 'foo' - >>> _get_toplevel_name(PackagePath('foo/__init__.py')) - 'foo' - >>> _get_toplevel_name(PackagePath('foo.pth')) - 'foo.pth' - >>> _get_toplevel_name(PackagePath('foo.dist-info')) - 'foo.dist-info' - """ - # Defer import of inspect for performance (python/cpython#118761) - import inspect - - return _topmost(name) or inspect.getmodulename(name) or str(name) - - -def _top_level_inferred(dist): - opt_names = set(map(_get_toplevel_name, always_iterable(dist.files))) - - def importable_name(name): - return '.' not in name - - return filter(importable_name, opt_names) diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_adapters.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_adapters.py deleted file mode 100644 index f5b30dd..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_adapters.py +++ /dev/null @@ -1,135 +0,0 @@ -import email.message -import email.policy -import re -import textwrap - -from ._text import FoldedCase - - -class RawPolicy(email.policy.EmailPolicy): - def fold(self, name, value): - folded = self.linesep.join( - textwrap.indent(value, prefix=' ' * 8, predicate=lambda line: True) - .lstrip() - .splitlines() - ) - return f'{name}: {folded}{self.linesep}' - - -class Message(email.message.Message): - r""" - Specialized Message subclass to handle metadata naturally. - - Reads values that may have newlines in them and converts the - payload to the Description. - - >>> msg_text = textwrap.dedent(''' - ... Name: Foo - ... Version: 3.0 - ... License: blah - ... de-blah - ... - ... First line of description. - ... Second line of description. - ... - ... Fourth line! - ... ''').lstrip().replace('', '') - >>> msg = Message(email.message_from_string(msg_text)) - >>> msg['Description'] - 'First line of description.\nSecond line of description.\n\nFourth line!\n' - - Message should render even if values contain newlines. - - >>> print(msg) - Name: Foo - Version: 3.0 - License: blah - de-blah - Description: First line of description. - Second line of description. - - Fourth line! - - - """ - - multiple_use_keys = set( - map( - FoldedCase, - [ - 'Classifier', - 'Obsoletes-Dist', - 'Platform', - 'Project-URL', - 'Provides-Dist', - 'Provides-Extra', - 'Requires-Dist', - 'Requires-External', - 'Supported-Platform', - 'Dynamic', - ], - ) - ) - """ - Keys that may be indicated multiple times per PEP 566. - """ - - def __new__(cls, orig: email.message.Message): - res = super().__new__(cls) - vars(res).update(vars(orig)) - return res - - def __init__(self, *args, **kwargs): - self._headers = self._repair_headers() - - # suppress spurious error from mypy - def __iter__(self): - return super().__iter__() - - def __getitem__(self, item): - """ - Override parent behavior to typical dict behavior. - - ``email.message.Message`` will emit None values for missing - keys. Typical mappings, including this ``Message``, will raise - a key error for missing keys. - - Ref python/importlib_metadata#371. - """ - res = super().__getitem__(item) - if res is None: - raise KeyError(item) - return res - - def _repair_headers(self): - def redent(value): - "Correct for RFC822 indentation" - indent = ' ' * 8 - if not value or '\n' + indent not in value: - return value - return textwrap.dedent(indent + value) - - headers = [(key, redent(value)) for key, value in vars(self)['_headers']] - if self._payload: - headers.append(('Description', self.get_payload())) - self.set_payload('') - return headers - - def as_string(self): - return super().as_string(policy=RawPolicy()) - - @property - def json(self): - """ - Convert PackageMetadata to a JSON-compatible format - per PEP 0566. - """ - - def transform(key): - value = self.get_all(key) if key in self.multiple_use_keys else self[key] - if key == 'Keywords': - value = re.split(r'\s+', value) - tk = key.lower().replace('-', '_') - return tk, value - - return dict(map(transform, map(FoldedCase, self))) diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_collections.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_collections.py deleted file mode 100644 index fc5045d..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_collections.py +++ /dev/null @@ -1,34 +0,0 @@ -import collections -import typing - - -# from jaraco.collections 3.3 -class FreezableDefaultDict(collections.defaultdict): - """ - Often it is desirable to prevent the mutation of - a default dict after its initial construction, such - as to prevent mutation during iteration. - - >>> dd = FreezableDefaultDict(list) - >>> dd[0].append('1') - >>> dd.freeze() - >>> dd[1] - [] - >>> len(dd) - 1 - """ - - def __missing__(self, key): - return getattr(self, '_frozen', super().__missing__)(key) - - def freeze(self): - self._frozen = lambda key: self.default_factory() - - -class Pair(typing.NamedTuple): - name: str - value: str - - @classmethod - def parse(cls, text): - return cls(*map(str.strip, text.split("=", 1))) diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_compat.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_compat.py deleted file mode 100644 index 01356d6..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_compat.py +++ /dev/null @@ -1,56 +0,0 @@ -import platform -import sys - -__all__ = ['install', 'NullFinder'] - - -def install(cls): - """ - Class decorator for installation on sys.meta_path. - - Adds the backport DistributionFinder to sys.meta_path and - attempts to disable the finder functionality of the stdlib - DistributionFinder. - """ - sys.meta_path.append(cls()) - disable_stdlib_finder() - return cls - - -def disable_stdlib_finder(): - """ - Give the backport primacy for discovering path-based distributions - by monkey-patching the stdlib O_O. - - See #91 for more background for rationale on this sketchy - behavior. - """ - - def matches(finder): - return getattr( - finder, '__module__', None - ) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions') - - for finder in filter(matches, sys.meta_path): # pragma: nocover - del finder.find_distributions - - -class NullFinder: - """ - A "Finder" (aka "MetaPathFinder") that never finds any modules, - but may find distributions. - """ - - @staticmethod - def find_spec(*args, **kwargs): - return None - - -def pypy_partial(val): - """ - Adjust for variable stacklevel on partial under PyPy. - - Workaround for #327. - """ - is_pypy = platform.python_implementation() == 'PyPy' - return val + is_pypy diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_functools.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_functools.py deleted file mode 100644 index 5dda6a2..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_functools.py +++ /dev/null @@ -1,104 +0,0 @@ -import functools -import types - - -# from jaraco.functools 3.3 -def method_cache(method, cache_wrapper=None): - """ - Wrap lru_cache to support storing the cache data in the object instances. - - Abstracts the common paradigm where the method explicitly saves an - underscore-prefixed protected property on first call and returns that - subsequently. - - >>> class MyClass: - ... calls = 0 - ... - ... @method_cache - ... def method(self, value): - ... self.calls += 1 - ... return value - - >>> a = MyClass() - >>> a.method(3) - 3 - >>> for x in range(75): - ... res = a.method(x) - >>> a.calls - 75 - - Note that the apparent behavior will be exactly like that of lru_cache - except that the cache is stored on each instance, so values in one - instance will not flush values from another, and when an instance is - deleted, so are the cached values for that instance. - - >>> b = MyClass() - >>> for x in range(35): - ... res = b.method(x) - >>> b.calls - 35 - >>> a.method(0) - 0 - >>> a.calls - 75 - - Note that if method had been decorated with ``functools.lru_cache()``, - a.calls would have been 76 (due to the cached value of 0 having been - flushed by the 'b' instance). - - Clear the cache with ``.cache_clear()`` - - >>> a.method.cache_clear() - - Same for a method that hasn't yet been called. - - >>> c = MyClass() - >>> c.method.cache_clear() - - Another cache wrapper may be supplied: - - >>> cache = functools.lru_cache(maxsize=2) - >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache) - >>> a = MyClass() - >>> a.method2() - 3 - - Caution - do not subsequently wrap the method with another decorator, such - as ``@property``, which changes the semantics of the function. - - See also - http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/ - for another implementation and additional justification. - """ - cache_wrapper = cache_wrapper or functools.lru_cache() - - def wrapper(self, *args, **kwargs): - # it's the first call, replace the method with a cached, bound method - bound_method = types.MethodType(method, self) - cached_method = cache_wrapper(bound_method) - setattr(self, method.__name__, cached_method) - return cached_method(*args, **kwargs) - - # Support cache clear even before cache has been created. - wrapper.cache_clear = lambda: None - - return wrapper - - -# From jaraco.functools 3.3 -def pass_none(func): - """ - Wrap func so it's not called if its first param is None - - >>> print_text = pass_none(print) - >>> print_text('text') - text - >>> print_text(None) - """ - - @functools.wraps(func) - def wrapper(param, *args, **kwargs): - if param is not None: - return func(param, *args, **kwargs) - - return wrapper diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_itertools.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_itertools.py deleted file mode 100644 index 79d3719..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_itertools.py +++ /dev/null @@ -1,171 +0,0 @@ -from collections import defaultdict, deque -from itertools import filterfalse - - -def unique_everseen(iterable, key=None): - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen = set() - seen_add = seen.add - if key is None: - for element in filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element - - -# copied from more_itertools 8.8 -def always_iterable(obj, base_type=(str, bytes)): - """If *obj* is iterable, return an iterator over its items:: - - >>> obj = (1, 2, 3) - >>> list(always_iterable(obj)) - [1, 2, 3] - - If *obj* is not iterable, return a one-item iterable containing *obj*:: - - >>> obj = 1 - >>> list(always_iterable(obj)) - [1] - - If *obj* is ``None``, return an empty iterable: - - >>> obj = None - >>> list(always_iterable(None)) - [] - - By default, binary and text strings are not considered iterable:: - - >>> obj = 'foo' - >>> list(always_iterable(obj)) - ['foo'] - - If *base_type* is set, objects for which ``isinstance(obj, base_type)`` - returns ``True`` won't be considered iterable. - - >>> obj = {'a': 1} - >>> list(always_iterable(obj)) # Iterate over the dict's keys - ['a'] - >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit - [{'a': 1}] - - Set *base_type* to ``None`` to avoid any special handling and treat objects - Python considers iterable as iterable: - - >>> obj = 'foo' - >>> list(always_iterable(obj, base_type=None)) - ['f', 'o', 'o'] - """ - if obj is None: - return iter(()) - - if (base_type is not None) and isinstance(obj, base_type): - return iter((obj,)) - - try: - return iter(obj) - except TypeError: - return iter((obj,)) - - -# Copied from more_itertools 10.3 -class bucket: - """Wrap *iterable* and return an object that buckets the iterable into - child iterables based on a *key* function. - - >>> iterable = ['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'b3'] - >>> s = bucket(iterable, key=lambda x: x[0]) # Bucket by 1st character - >>> sorted(list(s)) # Get the keys - ['a', 'b', 'c'] - >>> a_iterable = s['a'] - >>> next(a_iterable) - 'a1' - >>> next(a_iterable) - 'a2' - >>> list(s['b']) - ['b1', 'b2', 'b3'] - - The original iterable will be advanced and its items will be cached until - they are used by the child iterables. This may require significant storage. - - By default, attempting to select a bucket to which no items belong will - exhaust the iterable and cache all values. - If you specify a *validator* function, selected buckets will instead be - checked against it. - - >>> from itertools import count - >>> it = count(1, 2) # Infinite sequence of odd numbers - >>> key = lambda x: x % 10 # Bucket by last digit - >>> validator = lambda x: x in {1, 3, 5, 7, 9} # Odd digits only - >>> s = bucket(it, key=key, validator=validator) - >>> 2 in s - False - >>> list(s[2]) - [] - - """ - - def __init__(self, iterable, key, validator=None): - self._it = iter(iterable) - self._key = key - self._cache = defaultdict(deque) - self._validator = validator or (lambda x: True) - - def __contains__(self, value): - if not self._validator(value): - return False - - try: - item = next(self[value]) - except StopIteration: - return False - else: - self._cache[value].appendleft(item) - - return True - - def _get_values(self, value): - """ - Helper to yield items from the parent iterator that match *value*. - Items that don't match are stored in the local cache as they - are encountered. - """ - while True: - # If we've cached some items that match the target value, emit - # the first one and evict it from the cache. - if self._cache[value]: - yield self._cache[value].popleft() - # Otherwise we need to advance the parent iterator to search for - # a matching item, caching the rest. - else: - while True: - try: - item = next(self._it) - except StopIteration: - return - item_value = self._key(item) - if item_value == value: - yield item - break - elif self._validator(item_value): - self._cache[item_value].append(item) - - def __iter__(self): - for item in self._it: - item_value = self._key(item) - if self._validator(item_value): - self._cache[item_value].append(item) - - yield from self._cache.keys() - - def __getitem__(self, value): - if not self._validator(value): - return iter(()) - - return self._get_values(value) diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_meta.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_meta.py deleted file mode 100644 index 0c20eff..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_meta.py +++ /dev/null @@ -1,71 +0,0 @@ -from __future__ import annotations - -import os -from collections.abc import Iterator -from typing import ( - Any, - Protocol, - TypeVar, - overload, -) - -_T = TypeVar("_T") - - -class PackageMetadata(Protocol): - def __len__(self) -> int: ... # pragma: no cover - - def __contains__(self, item: str) -> bool: ... # pragma: no cover - - def __getitem__(self, key: str) -> str: ... # pragma: no cover - - def __iter__(self) -> Iterator[str]: ... # pragma: no cover - - @overload - def get( - self, name: str, failobj: None = None - ) -> str | None: ... # pragma: no cover - - @overload - def get(self, name: str, failobj: _T) -> str | _T: ... # pragma: no cover - - # overload per python/importlib_metadata#435 - @overload - def get_all( - self, name: str, failobj: None = None - ) -> list[Any] | None: ... # pragma: no cover - - @overload - def get_all(self, name: str, failobj: _T) -> list[Any] | _T: - """ - Return all values associated with a possibly multi-valued key. - """ - - @property - def json(self) -> dict[str, str | list[str]]: - """ - A JSON-compatible form of the metadata. - """ - - -class SimplePath(Protocol): - """ - A minimal subset of pathlib.Path required by Distribution. - """ - - def joinpath( - self, other: str | os.PathLike[str] - ) -> SimplePath: ... # pragma: no cover - - def __truediv__( - self, other: str | os.PathLike[str] - ) -> SimplePath: ... # pragma: no cover - - @property - def parent(self) -> SimplePath: ... # pragma: no cover - - def read_text(self, encoding=None) -> str: ... # pragma: no cover - - def read_bytes(self) -> bytes: ... # pragma: no cover - - def exists(self) -> bool: ... # pragma: no cover diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_text.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_text.py deleted file mode 100644 index c88cfbb..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_text.py +++ /dev/null @@ -1,99 +0,0 @@ -import re - -from ._functools import method_cache - - -# from jaraco.text 3.5 -class FoldedCase(str): - """ - A case insensitive string class; behaves just like str - except compares equal when the only variation is case. - - >>> s = FoldedCase('hello world') - - >>> s == 'Hello World' - True - - >>> 'Hello World' == s - True - - >>> s != 'Hello World' - False - - >>> s.index('O') - 4 - - >>> s.split('O') - ['hell', ' w', 'rld'] - - >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) - ['alpha', 'Beta', 'GAMMA'] - - Sequence membership is straightforward. - - >>> "Hello World" in [s] - True - >>> s in ["Hello World"] - True - - You may test for set inclusion, but candidate and elements - must both be folded. - - >>> FoldedCase("Hello World") in {s} - True - >>> s in {FoldedCase("Hello World")} - True - - String inclusion works as long as the FoldedCase object - is on the right. - - >>> "hello" in FoldedCase("Hello World") - True - - But not if the FoldedCase object is on the left: - - >>> FoldedCase('hello') in 'Hello World' - False - - In that case, use in_: - - >>> FoldedCase('hello').in_('Hello World') - True - - >>> FoldedCase('hello') > FoldedCase('Hello') - False - """ - - def __lt__(self, other): - return self.lower() < other.lower() - - def __gt__(self, other): - return self.lower() > other.lower() - - def __eq__(self, other): - return self.lower() == other.lower() - - def __ne__(self, other): - return self.lower() != other.lower() - - def __hash__(self): - return hash(self.lower()) - - def __contains__(self, other): - return super().lower().__contains__(other.lower()) - - def in_(self, other): - "Does self appear in other?" - return self in FoldedCase(other) - - # cache lower since it's likely to be called frequently. - @method_cache - def lower(self): - return super().lower() - - def index(self, sub): - return self.lower().index(sub.lower()) - - def split(self, splitter=' ', maxsplit=0): - pattern = re.compile(re.escape(splitter), re.I) - return pattern.split(self, maxsplit) diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/_typing.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/_typing.py deleted file mode 100644 index 32b1d2b..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/_typing.py +++ /dev/null @@ -1,15 +0,0 @@ -import functools -import typing - -from ._meta import PackageMetadata - -md_none = functools.partial(typing.cast, PackageMetadata) -""" -Suppress type errors for optional metadata. - -Although Distribution.metadata can return None when metadata is corrupt -and thus None, allow callers to assume it's not None and crash if -that's the case. - -# python/importlib_metadata#493 -""" diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/__init__.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py311.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py311.py deleted file mode 100644 index 3a53274..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py311.py +++ /dev/null @@ -1,22 +0,0 @@ -import os -import pathlib -import sys -import types - - -def wrap(path): # pragma: no cover - """ - Workaround for https://github.com/python/cpython/issues/84538 - to add backward compatibility for walk_up=True. - An example affected package is dask-labextension, which uses - jupyter-packaging to install JupyterLab javascript files outside - of site-packages. - """ - - def relative_to(root, *, walk_up=False): - return pathlib.Path(os.path.relpath(path, root)) - - return types.SimpleNamespace(relative_to=relative_to) - - -relative_fix = wrap if sys.version_info < (3, 12) else lambda x: x diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py39.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py39.py deleted file mode 100644 index 3eb9c01..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/compat/py39.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Compatibility layer with Python 3.8/3.9 -""" - -from __future__ import annotations - -from typing import TYPE_CHECKING, Any - -if TYPE_CHECKING: # pragma: no cover - # Prevent circular imports on runtime. - from .. import Distribution, EntryPoint -else: - Distribution = EntryPoint = Any - -from .._typing import md_none - - -def normalized_name(dist: Distribution) -> str | None: - """ - Honor name normalization for distributions that don't provide ``_normalized_name``. - """ - try: - return dist._normalized_name - except AttributeError: - from .. import Prepared # -> delay to prevent circular imports. - - return Prepared.normalize( - getattr(dist, "name", None) or md_none(dist.metadata)['Name'] - ) - - -def ep_matches(ep: EntryPoint, **params) -> bool: - """ - Workaround for ``EntryPoint`` objects without the ``matches`` method. - """ - try: - return ep.matches(**params) - except AttributeError: - from .. import EntryPoint # -> delay to prevent circular imports. - - # Reconstruct the EntryPoint object to make sure it is compatible. - return EntryPoint(ep.name, ep.value, ep.group).matches(**params) diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/diagnose.py b/serverenv/lib/python3.9/site-packages/importlib_metadata/diagnose.py deleted file mode 100644 index e405471..0000000 --- a/serverenv/lib/python3.9/site-packages/importlib_metadata/diagnose.py +++ /dev/null @@ -1,21 +0,0 @@ -import sys - -from . import Distribution - - -def inspect(path): - print("Inspecting", path) - dists = list(Distribution.discover(path=[path])) - if not dists: - return - print("Found", len(dists), "packages:", end=' ') - print(', '.join(dist.name for dist in dists)) - - -def run(): - for path in sys.path: - inspect(path) - - -if __name__ == '__main__': - run() diff --git a/serverenv/lib/python3.9/site-packages/importlib_metadata/py.typed b/serverenv/lib/python3.9/site-packages/importlib_metadata/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt b/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt deleted file mode 100644 index 7b190ca..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2011 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/METADATA deleted file mode 100644 index ddf5464..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/METADATA +++ /dev/null @@ -1,60 +0,0 @@ -Metadata-Version: 2.1 -Name: itsdangerous -Version: 2.2.0 -Summary: Safely pass data to untrusted environments and back. -Maintainer-email: Pallets -Requires-Python: >=3.8 -Description-Content-Type: text/markdown -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Typing :: Typed -Project-URL: Changes, https://itsdangerous.palletsprojects.com/changes/ -Project-URL: Chat, https://discord.gg/pallets -Project-URL: Documentation, https://itsdangerous.palletsprojects.com/ -Project-URL: Donate, https://palletsprojects.com/donate -Project-URL: Source, https://github.com/pallets/itsdangerous/ - -# ItsDangerous - -... so better sign this - -Various helpers to pass data to untrusted environments and to get it -back safe and sound. Data is cryptographically signed to ensure that a -token has not been tampered with. - -It's possible to customize how data is serialized. Data is compressed as -needed. A timestamp can be added and verified automatically while -loading a token. - - -## A Simple Example - -Here's how you could generate a token for transmitting a user's id and -name between web requests. - -```python -from itsdangerous import URLSafeSerializer -auth_s = URLSafeSerializer("secret key", "auth") -token = auth_s.dumps({"id": 5, "name": "itsdangerous"}) - -print(token) -# eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg - -data = auth_s.loads(token) -print(data["name"]) -# itsdangerous -``` - - -## Donate - -The Pallets organization develops and supports ItsDangerous and other -popular packages. In order to grow the community of contributors and -users, and allow the maintainers to devote more time to the projects, -[please donate today][]. - -[please donate today]: https://palletsprojects.com/donate - diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/RECORD deleted file mode 100644 index ad787ec..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/RECORD +++ /dev/null @@ -1,22 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/_json.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/encoding.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/exc.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/serializer.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/signer.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/timed.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/itsdangerous/url_safe.cpython-39.pyc,, -itsdangerous-2.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -itsdangerous-2.2.0.dist-info/LICENSE.txt,sha256=Y68JiRtr6K0aQlLtQ68PTvun_JSOIoNnvtfzxa4LCdc,1475 -itsdangerous-2.2.0.dist-info/METADATA,sha256=0rk0-1ZwihuU5DnwJVwPWoEI4yWOyCexih3JyZHblhE,1924 -itsdangerous-2.2.0.dist-info/RECORD,, -itsdangerous-2.2.0.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 -itsdangerous/__init__.py,sha256=4SK75sCe29xbRgQE1ZQtMHnKUuZYAf3bSpZOrff1IAY,1427 -itsdangerous/_json.py,sha256=wPQGmge2yZ9328EHKF6gadGeyGYCJQKxtU-iLKE6UnA,473 -itsdangerous/encoding.py,sha256=wwTz5q_3zLcaAdunk6_vSoStwGqYWe307Zl_U87aRFM,1409 -itsdangerous/exc.py,sha256=Rr3exo0MRFEcPZltwecyK16VV1bE2K9_F1-d-ljcUn4,3201 -itsdangerous/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -itsdangerous/serializer.py,sha256=PmdwADLqkSyQLZ0jOKAgDsAW4k_H0TlA71Ei3z0C5aI,15601 -itsdangerous/signer.py,sha256=YO0CV7NBvHA6j549REHJFUjUojw2pHqwcUpQnU7yNYQ,9647 -itsdangerous/timed.py,sha256=6RvDMqNumGMxf0-HlpaZdN9PUQQmRvrQGplKhxuivUs,8083 -itsdangerous/url_safe.py,sha256=az4e5fXi_vs-YbWj8YZwn4wiVKfeD--GEKRT5Ueu4P4,2505 diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/WHEEL deleted file mode 100644 index 3b5e64b..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous-2.2.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.9.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/__init__.py b/serverenv/lib/python3.9/site-packages/itsdangerous/__init__.py deleted file mode 100644 index ea55256..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import annotations - -import typing as t - -from .encoding import base64_decode as base64_decode -from .encoding import base64_encode as base64_encode -from .encoding import want_bytes as want_bytes -from .exc import BadData as BadData -from .exc import BadHeader as BadHeader -from .exc import BadPayload as BadPayload -from .exc import BadSignature as BadSignature -from .exc import BadTimeSignature as BadTimeSignature -from .exc import SignatureExpired as SignatureExpired -from .serializer import Serializer as Serializer -from .signer import HMACAlgorithm as HMACAlgorithm -from .signer import NoneAlgorithm as NoneAlgorithm -from .signer import Signer as Signer -from .timed import TimedSerializer as TimedSerializer -from .timed import TimestampSigner as TimestampSigner -from .url_safe import URLSafeSerializer as URLSafeSerializer -from .url_safe import URLSafeTimedSerializer as URLSafeTimedSerializer - - -def __getattr__(name: str) -> t.Any: - if name == "__version__": - import importlib.metadata - import warnings - - warnings.warn( - "The '__version__' attribute is deprecated and will be removed in" - " ItsDangerous 2.3. Use feature detection or" - " 'importlib.metadata.version(\"itsdangerous\")' instead.", - DeprecationWarning, - stacklevel=2, - ) - return importlib.metadata.version("itsdangerous") - - raise AttributeError(name) diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/_json.py b/serverenv/lib/python3.9/site-packages/itsdangerous/_json.py deleted file mode 100644 index fc23fea..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/_json.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -import json as _json -import typing as t - - -class _CompactJSON: - """Wrapper around json module that strips whitespace.""" - - @staticmethod - def loads(payload: str | bytes) -> t.Any: - return _json.loads(payload) - - @staticmethod - def dumps(obj: t.Any, **kwargs: t.Any) -> str: - kwargs.setdefault("ensure_ascii", False) - kwargs.setdefault("separators", (",", ":")) - return _json.dumps(obj, **kwargs) diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/encoding.py b/serverenv/lib/python3.9/site-packages/itsdangerous/encoding.py deleted file mode 100644 index f5ca80f..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/encoding.py +++ /dev/null @@ -1,54 +0,0 @@ -from __future__ import annotations - -import base64 -import string -import struct -import typing as t - -from .exc import BadData - - -def want_bytes( - s: str | bytes, encoding: str = "utf-8", errors: str = "strict" -) -> bytes: - if isinstance(s, str): - s = s.encode(encoding, errors) - - return s - - -def base64_encode(string: str | bytes) -> bytes: - """Base64 encode a string of bytes or text. The resulting bytes are - safe to use in URLs. - """ - string = want_bytes(string) - return base64.urlsafe_b64encode(string).rstrip(b"=") - - -def base64_decode(string: str | bytes) -> bytes: - """Base64 decode a URL-safe string of bytes or text. The result is - bytes. - """ - string = want_bytes(string, encoding="ascii", errors="ignore") - string += b"=" * (-len(string) % 4) - - try: - return base64.urlsafe_b64decode(string) - except (TypeError, ValueError) as e: - raise BadData("Invalid base64-encoded data") from e - - -# The alphabet used by base64.urlsafe_* -_base64_alphabet = f"{string.ascii_letters}{string.digits}-_=".encode("ascii") - -_int64_struct = struct.Struct(">Q") -_int_to_bytes = _int64_struct.pack -_bytes_to_int = t.cast("t.Callable[[bytes], tuple[int]]", _int64_struct.unpack) - - -def int_to_bytes(num: int) -> bytes: - return _int_to_bytes(num).lstrip(b"\x00") - - -def bytes_to_int(bytestr: bytes) -> int: - return _bytes_to_int(bytestr.rjust(8, b"\x00"))[0] diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/exc.py b/serverenv/lib/python3.9/site-packages/itsdangerous/exc.py deleted file mode 100644 index a75adcd..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/exc.py +++ /dev/null @@ -1,106 +0,0 @@ -from __future__ import annotations - -import typing as t -from datetime import datetime - - -class BadData(Exception): - """Raised if bad data of any sort was encountered. This is the base - for all exceptions that ItsDangerous defines. - - .. versionadded:: 0.15 - """ - - def __init__(self, message: str): - super().__init__(message) - self.message = message - - def __str__(self) -> str: - return self.message - - -class BadSignature(BadData): - """Raised if a signature does not match.""" - - def __init__(self, message: str, payload: t.Any | None = None): - super().__init__(message) - - #: The payload that failed the signature test. In some - #: situations you might still want to inspect this, even if - #: you know it was tampered with. - #: - #: .. versionadded:: 0.14 - self.payload: t.Any | None = payload - - -class BadTimeSignature(BadSignature): - """Raised if a time-based signature is invalid. This is a subclass - of :class:`BadSignature`. - """ - - def __init__( - self, - message: str, - payload: t.Any | None = None, - date_signed: datetime | None = None, - ): - super().__init__(message, payload) - - #: If the signature expired this exposes the date of when the - #: signature was created. This can be helpful in order to - #: tell the user how long a link has been gone stale. - #: - #: .. versionchanged:: 2.0 - #: The datetime value is timezone-aware rather than naive. - #: - #: .. versionadded:: 0.14 - self.date_signed = date_signed - - -class SignatureExpired(BadTimeSignature): - """Raised if a signature timestamp is older than ``max_age``. This - is a subclass of :exc:`BadTimeSignature`. - """ - - -class BadHeader(BadSignature): - """Raised if a signed header is invalid in some form. This only - happens for serializers that have a header that goes with the - signature. - - .. versionadded:: 0.24 - """ - - def __init__( - self, - message: str, - payload: t.Any | None = None, - header: t.Any | None = None, - original_error: Exception | None = None, - ): - super().__init__(message, payload) - - #: If the header is actually available but just malformed it - #: might be stored here. - self.header: t.Any | None = header - - #: If available, the error that indicates why the payload was - #: not valid. This might be ``None``. - self.original_error: Exception | None = original_error - - -class BadPayload(BadData): - """Raised if a payload is invalid. This could happen if the payload - is loaded despite an invalid signature, or if there is a mismatch - between the serializer and deserializer. The original exception - that occurred during loading is stored on as :attr:`original_error`. - - .. versionadded:: 0.15 - """ - - def __init__(self, message: str, original_error: Exception | None = None): - super().__init__(message) - - #: If available, the error that indicates why the payload was - #: not valid. This might be ``None``. - self.original_error: Exception | None = original_error diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/py.typed b/serverenv/lib/python3.9/site-packages/itsdangerous/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/serializer.py b/serverenv/lib/python3.9/site-packages/itsdangerous/serializer.py deleted file mode 100644 index 5ddf387..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/serializer.py +++ /dev/null @@ -1,406 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import json -import typing as t - -from .encoding import want_bytes -from .exc import BadPayload -from .exc import BadSignature -from .signer import _make_keys_list -from .signer import Signer - -if t.TYPE_CHECKING: - import typing_extensions as te - - # This should be either be str or bytes. To avoid having to specify the - # bound type, it falls back to a union if structural matching fails. - _TSerialized = te.TypeVar( - "_TSerialized", bound=t.Union[str, bytes], default=t.Union[str, bytes] - ) -else: - # Still available at runtime on Python < 3.13, but without the default. - _TSerialized = t.TypeVar("_TSerialized", bound=t.Union[str, bytes]) - - -class _PDataSerializer(t.Protocol[_TSerialized]): - def loads(self, payload: _TSerialized, /) -> t.Any: ... - # A signature with additional arguments is not handled correctly by type - # checkers right now, so an overload is used below for serializers that - # don't match this strict protocol. - def dumps(self, obj: t.Any, /) -> _TSerialized: ... - - -# Use TypeIs once it's available in typing_extensions or 3.13. -def is_text_serializer( - serializer: _PDataSerializer[t.Any], -) -> te.TypeGuard[_PDataSerializer[str]]: - """Checks whether a serializer generates text or binary.""" - return isinstance(serializer.dumps({}), str) - - -class Serializer(t.Generic[_TSerialized]): - """A serializer wraps a :class:`~itsdangerous.signer.Signer` to - enable serializing and securely signing data other than bytes. It - can unsign to verify that the data hasn't been changed. - - The serializer provides :meth:`dumps` and :meth:`loads`, similar to - :mod:`json`, and by default uses :mod:`json` internally to serialize - the data to bytes. - - The secret key should be a random string of ``bytes`` and should not - be saved to code or version control. Different salts should be used - to distinguish signing in different contexts. See :doc:`/concepts` - for information about the security of the secret key and salt. - - :param secret_key: The secret key to sign and verify with. Can be a - list of keys, oldest to newest, to support key rotation. - :param salt: Extra key to combine with ``secret_key`` to distinguish - signatures in different contexts. - :param serializer: An object that provides ``dumps`` and ``loads`` - methods for serializing data to a string. Defaults to - :attr:`default_serializer`, which defaults to :mod:`json`. - :param serializer_kwargs: Keyword arguments to pass when calling - ``serializer.dumps``. - :param signer: A ``Signer`` class to instantiate when signing data. - Defaults to :attr:`default_signer`, which defaults to - :class:`~itsdangerous.signer.Signer`. - :param signer_kwargs: Keyword arguments to pass when instantiating - the ``Signer`` class. - :param fallback_signers: List of signer parameters to try when - unsigning with the default signer fails. Each item can be a dict - of ``signer_kwargs``, a ``Signer`` class, or a tuple of - ``(signer, signer_kwargs)``. Defaults to - :attr:`default_fallback_signers`. - - .. versionchanged:: 2.0 - Added support for key rotation by passing a list to - ``secret_key``. - - .. versionchanged:: 2.0 - Removed the default SHA-512 fallback signer from - ``default_fallback_signers``. - - .. versionchanged:: 1.1 - Added support for ``fallback_signers`` and configured a default - SHA-512 fallback. This fallback is for users who used the yanked - 1.0.0 release which defaulted to SHA-512. - - .. versionchanged:: 0.14 - The ``signer`` and ``signer_kwargs`` parameters were added to - the constructor. - """ - - #: The default serialization module to use to serialize data to a - #: string internally. The default is :mod:`json`, but can be changed - #: to any object that provides ``dumps`` and ``loads`` methods. - default_serializer: _PDataSerializer[t.Any] = json - - #: The default ``Signer`` class to instantiate when signing data. - #: The default is :class:`itsdangerous.signer.Signer`. - default_signer: type[Signer] = Signer - - #: The default fallback signers to try when unsigning fails. - default_fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] = [] - - # Serializer[str] if no data serializer is provided, or if it returns str. - @t.overload - def __init__( - self: Serializer[str], - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], - salt: str | bytes | None = b"itsdangerous", - serializer: None | _PDataSerializer[str] = None, - serializer_kwargs: dict[str, t.Any] | None = None, - signer: type[Signer] | None = None, - signer_kwargs: dict[str, t.Any] | None = None, - fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] - | None = None, - ): ... - - # Serializer[bytes] with a bytes data serializer positional argument. - @t.overload - def __init__( - self: Serializer[bytes], - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], - salt: str | bytes | None, - serializer: _PDataSerializer[bytes], - serializer_kwargs: dict[str, t.Any] | None = None, - signer: type[Signer] | None = None, - signer_kwargs: dict[str, t.Any] | None = None, - fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] - | None = None, - ): ... - - # Serializer[bytes] with a bytes data serializer keyword argument. - @t.overload - def __init__( - self: Serializer[bytes], - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], - salt: str | bytes | None = b"itsdangerous", - *, - serializer: _PDataSerializer[bytes], - serializer_kwargs: dict[str, t.Any] | None = None, - signer: type[Signer] | None = None, - signer_kwargs: dict[str, t.Any] | None = None, - fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] - | None = None, - ): ... - - # Fall back with a positional argument. If the strict signature of - # _PDataSerializer doesn't match, fall back to a union, requiring the user - # to specify the type. - @t.overload - def __init__( - self, - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], - salt: str | bytes | None, - serializer: t.Any, - serializer_kwargs: dict[str, t.Any] | None = None, - signer: type[Signer] | None = None, - signer_kwargs: dict[str, t.Any] | None = None, - fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] - | None = None, - ): ... - - # Fall back with a keyword argument. - @t.overload - def __init__( - self, - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], - salt: str | bytes | None = b"itsdangerous", - *, - serializer: t.Any, - serializer_kwargs: dict[str, t.Any] | None = None, - signer: type[Signer] | None = None, - signer_kwargs: dict[str, t.Any] | None = None, - fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] - | None = None, - ): ... - - def __init__( - self, - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], - salt: str | bytes | None = b"itsdangerous", - serializer: t.Any | None = None, - serializer_kwargs: dict[str, t.Any] | None = None, - signer: type[Signer] | None = None, - signer_kwargs: dict[str, t.Any] | None = None, - fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] - | None = None, - ): - #: The list of secret keys to try for verifying signatures, from - #: oldest to newest. The newest (last) key is used for signing. - #: - #: This allows a key rotation system to keep a list of allowed - #: keys and remove expired ones. - self.secret_keys: list[bytes] = _make_keys_list(secret_key) - - if salt is not None: - salt = want_bytes(salt) - # if salt is None then the signer's default is used - - self.salt = salt - - if serializer is None: - serializer = self.default_serializer - - self.serializer: _PDataSerializer[_TSerialized] = serializer - self.is_text_serializer: bool = is_text_serializer(serializer) - - if signer is None: - signer = self.default_signer - - self.signer: type[Signer] = signer - self.signer_kwargs: dict[str, t.Any] = signer_kwargs or {} - - if fallback_signers is None: - fallback_signers = list(self.default_fallback_signers) - - self.fallback_signers: list[ - dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] - ] = fallback_signers - self.serializer_kwargs: dict[str, t.Any] = serializer_kwargs or {} - - @property - def secret_key(self) -> bytes: - """The newest (last) entry in the :attr:`secret_keys` list. This - is for compatibility from before key rotation support was added. - """ - return self.secret_keys[-1] - - def load_payload( - self, payload: bytes, serializer: _PDataSerializer[t.Any] | None = None - ) -> t.Any: - """Loads the encoded object. This function raises - :class:`.BadPayload` if the payload is not valid. The - ``serializer`` parameter can be used to override the serializer - stored on the class. The encoded ``payload`` should always be - bytes. - """ - if serializer is None: - use_serializer = self.serializer - is_text = self.is_text_serializer - else: - use_serializer = serializer - is_text = is_text_serializer(serializer) - - try: - if is_text: - return use_serializer.loads(payload.decode("utf-8")) # type: ignore[arg-type] - - return use_serializer.loads(payload) # type: ignore[arg-type] - except Exception as e: - raise BadPayload( - "Could not load the payload because an exception" - " occurred on unserializing the data.", - original_error=e, - ) from e - - def dump_payload(self, obj: t.Any) -> bytes: - """Dumps the encoded object. The return value is always bytes. - If the internal serializer returns text, the value will be - encoded as UTF-8. - """ - return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs)) - - def make_signer(self, salt: str | bytes | None = None) -> Signer: - """Creates a new instance of the signer to be used. The default - implementation uses the :class:`.Signer` base class. - """ - if salt is None: - salt = self.salt - - return self.signer(self.secret_keys, salt=salt, **self.signer_kwargs) - - def iter_unsigners(self, salt: str | bytes | None = None) -> cabc.Iterator[Signer]: - """Iterates over all signers to be tried for unsigning. Starts - with the configured signer, then constructs each signer - specified in ``fallback_signers``. - """ - if salt is None: - salt = self.salt - - yield self.make_signer(salt) - - for fallback in self.fallback_signers: - if isinstance(fallback, dict): - kwargs = fallback - fallback = self.signer - elif isinstance(fallback, tuple): - fallback, kwargs = fallback - else: - kwargs = self.signer_kwargs - - for secret_key in self.secret_keys: - yield fallback(secret_key, salt=salt, **kwargs) - - def dumps(self, obj: t.Any, salt: str | bytes | None = None) -> _TSerialized: - """Returns a signed string serialized with the internal - serializer. The return value can be either a byte or unicode - string depending on the format of the internal serializer. - """ - payload = want_bytes(self.dump_payload(obj)) - rv = self.make_signer(salt).sign(payload) - - if self.is_text_serializer: - return rv.decode("utf-8") # type: ignore[return-value] - - return rv # type: ignore[return-value] - - def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> None: - """Like :meth:`dumps` but dumps into a file. The file handle has - to be compatible with what the internal serializer expects. - """ - f.write(self.dumps(obj, salt)) - - def loads( - self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any - ) -> t.Any: - """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the - signature validation fails. - """ - s = want_bytes(s) - last_exception = None - - for signer in self.iter_unsigners(salt): - try: - return self.load_payload(signer.unsign(s)) - except BadSignature as err: - last_exception = err - - raise t.cast(BadSignature, last_exception) - - def load(self, f: t.IO[t.Any], salt: str | bytes | None = None) -> t.Any: - """Like :meth:`loads` but loads from a file.""" - return self.loads(f.read(), salt) - - def loads_unsafe( - self, s: str | bytes, salt: str | bytes | None = None - ) -> tuple[bool, t.Any]: - """Like :meth:`loads` but without verifying the signature. This - is potentially very dangerous to use depending on how your - serializer works. The return value is ``(signature_valid, - payload)`` instead of just the payload. The first item will be a - boolean that indicates if the signature is valid. This function - never fails. - - Use it for debugging only and if you know that your serializer - module is not exploitable (for example, do not use it with a - pickle serializer). - - .. versionadded:: 0.15 - """ - return self._loads_unsafe_impl(s, salt) - - def _loads_unsafe_impl( - self, - s: str | bytes, - salt: str | bytes | None, - load_kwargs: dict[str, t.Any] | None = None, - load_payload_kwargs: dict[str, t.Any] | None = None, - ) -> tuple[bool, t.Any]: - """Low level helper function to implement :meth:`loads_unsafe` - in serializer subclasses. - """ - if load_kwargs is None: - load_kwargs = {} - - try: - return True, self.loads(s, salt=salt, **load_kwargs) - except BadSignature as e: - if e.payload is None: - return False, None - - if load_payload_kwargs is None: - load_payload_kwargs = {} - - try: - return ( - False, - self.load_payload(e.payload, **load_payload_kwargs), - ) - except BadPayload: - return False, None - - def load_unsafe( - self, f: t.IO[t.Any], salt: str | bytes | None = None - ) -> tuple[bool, t.Any]: - """Like :meth:`loads_unsafe` but loads from a file. - - .. versionadded:: 0.15 - """ - return self.loads_unsafe(f.read(), salt=salt) diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/signer.py b/serverenv/lib/python3.9/site-packages/itsdangerous/signer.py deleted file mode 100644 index e324dc0..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/signer.py +++ /dev/null @@ -1,266 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import hashlib -import hmac -import typing as t - -from .encoding import _base64_alphabet -from .encoding import base64_decode -from .encoding import base64_encode -from .encoding import want_bytes -from .exc import BadSignature - - -class SigningAlgorithm: - """Subclasses must implement :meth:`get_signature` to provide - signature generation functionality. - """ - - def get_signature(self, key: bytes, value: bytes) -> bytes: - """Returns the signature for the given key and value.""" - raise NotImplementedError() - - def verify_signature(self, key: bytes, value: bytes, sig: bytes) -> bool: - """Verifies the given signature matches the expected - signature. - """ - return hmac.compare_digest(sig, self.get_signature(key, value)) - - -class NoneAlgorithm(SigningAlgorithm): - """Provides an algorithm that does not perform any signing and - returns an empty signature. - """ - - def get_signature(self, key: bytes, value: bytes) -> bytes: - return b"" - - -def _lazy_sha1(string: bytes = b"") -> t.Any: - """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include - SHA-1, in which case the import and use as a default would fail before the - developer can configure something else. - """ - return hashlib.sha1(string) - - -class HMACAlgorithm(SigningAlgorithm): - """Provides signature generation using HMACs.""" - - #: The digest method to use with the MAC algorithm. This defaults to - #: SHA1, but can be changed to any other function in the hashlib - #: module. - default_digest_method: t.Any = staticmethod(_lazy_sha1) - - def __init__(self, digest_method: t.Any = None): - if digest_method is None: - digest_method = self.default_digest_method - - self.digest_method: t.Any = digest_method - - def get_signature(self, key: bytes, value: bytes) -> bytes: - mac = hmac.new(key, msg=value, digestmod=self.digest_method) - return mac.digest() - - -def _make_keys_list( - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], -) -> list[bytes]: - if isinstance(secret_key, (str, bytes)): - return [want_bytes(secret_key)] - - return [want_bytes(s) for s in secret_key] # pyright: ignore - - -class Signer: - """A signer securely signs bytes, then unsigns them to verify that - the value hasn't been changed. - - The secret key should be a random string of ``bytes`` and should not - be saved to code or version control. Different salts should be used - to distinguish signing in different contexts. See :doc:`/concepts` - for information about the security of the secret key and salt. - - :param secret_key: The secret key to sign and verify with. Can be a - list of keys, oldest to newest, to support key rotation. - :param salt: Extra key to combine with ``secret_key`` to distinguish - signatures in different contexts. - :param sep: Separator between the signature and value. - :param key_derivation: How to derive the signing key from the secret - key and salt. Possible values are ``concat``, ``django-concat``, - or ``hmac``. Defaults to :attr:`default_key_derivation`, which - defaults to ``django-concat``. - :param digest_method: Hash function to use when generating the HMAC - signature. Defaults to :attr:`default_digest_method`, which - defaults to :func:`hashlib.sha1`. Note that the security of the - hash alone doesn't apply when used intermediately in HMAC. - :param algorithm: A :class:`SigningAlgorithm` instance to use - instead of building a default :class:`HMACAlgorithm` with the - ``digest_method``. - - .. versionchanged:: 2.0 - Added support for key rotation by passing a list to - ``secret_key``. - - .. versionchanged:: 0.18 - ``algorithm`` was added as an argument to the class constructor. - - .. versionchanged:: 0.14 - ``key_derivation`` and ``digest_method`` were added as arguments - to the class constructor. - """ - - #: The default digest method to use for the signer. The default is - #: :func:`hashlib.sha1`, but can be changed to any :mod:`hashlib` or - #: compatible object. Note that the security of the hash alone - #: doesn't apply when used intermediately in HMAC. - #: - #: .. versionadded:: 0.14 - default_digest_method: t.Any = staticmethod(_lazy_sha1) - - #: The default scheme to use to derive the signing key from the - #: secret key and salt. The default is ``django-concat``. Possible - #: values are ``concat``, ``django-concat``, and ``hmac``. - #: - #: .. versionadded:: 0.14 - default_key_derivation: str = "django-concat" - - def __init__( - self, - secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], - salt: str | bytes | None = b"itsdangerous.Signer", - sep: str | bytes = b".", - key_derivation: str | None = None, - digest_method: t.Any | None = None, - algorithm: SigningAlgorithm | None = None, - ): - #: The list of secret keys to try for verifying signatures, from - #: oldest to newest. The newest (last) key is used for signing. - #: - #: This allows a key rotation system to keep a list of allowed - #: keys and remove expired ones. - self.secret_keys: list[bytes] = _make_keys_list(secret_key) - self.sep: bytes = want_bytes(sep) - - if self.sep in _base64_alphabet: - raise ValueError( - "The given separator cannot be used because it may be" - " contained in the signature itself. ASCII letters," - " digits, and '-_=' must not be used." - ) - - if salt is not None: - salt = want_bytes(salt) - else: - salt = b"itsdangerous.Signer" - - self.salt = salt - - if key_derivation is None: - key_derivation = self.default_key_derivation - - self.key_derivation: str = key_derivation - - if digest_method is None: - digest_method = self.default_digest_method - - self.digest_method: t.Any = digest_method - - if algorithm is None: - algorithm = HMACAlgorithm(self.digest_method) - - self.algorithm: SigningAlgorithm = algorithm - - @property - def secret_key(self) -> bytes: - """The newest (last) entry in the :attr:`secret_keys` list. This - is for compatibility from before key rotation support was added. - """ - return self.secret_keys[-1] - - def derive_key(self, secret_key: str | bytes | None = None) -> bytes: - """This method is called to derive the key. The default key - derivation choices can be overridden here. Key derivation is not - intended to be used as a security method to make a complex key - out of a short password. Instead you should use large random - secret keys. - - :param secret_key: A specific secret key to derive from. - Defaults to the last item in :attr:`secret_keys`. - - .. versionchanged:: 2.0 - Added the ``secret_key`` parameter. - """ - if secret_key is None: - secret_key = self.secret_keys[-1] - else: - secret_key = want_bytes(secret_key) - - if self.key_derivation == "concat": - return t.cast(bytes, self.digest_method(self.salt + secret_key).digest()) - elif self.key_derivation == "django-concat": - return t.cast( - bytes, self.digest_method(self.salt + b"signer" + secret_key).digest() - ) - elif self.key_derivation == "hmac": - mac = hmac.new(secret_key, digestmod=self.digest_method) - mac.update(self.salt) - return mac.digest() - elif self.key_derivation == "none": - return secret_key - else: - raise TypeError("Unknown key derivation method") - - def get_signature(self, value: str | bytes) -> bytes: - """Returns the signature for the given value.""" - value = want_bytes(value) - key = self.derive_key() - sig = self.algorithm.get_signature(key, value) - return base64_encode(sig) - - def sign(self, value: str | bytes) -> bytes: - """Signs the given string.""" - value = want_bytes(value) - return value + self.sep + self.get_signature(value) - - def verify_signature(self, value: str | bytes, sig: str | bytes) -> bool: - """Verifies the signature for the given value.""" - try: - sig = base64_decode(sig) - except Exception: - return False - - value = want_bytes(value) - - for secret_key in reversed(self.secret_keys): - key = self.derive_key(secret_key) - - if self.algorithm.verify_signature(key, value, sig): - return True - - return False - - def unsign(self, signed_value: str | bytes) -> bytes: - """Unsigns the given string.""" - signed_value = want_bytes(signed_value) - - if self.sep not in signed_value: - raise BadSignature(f"No {self.sep!r} found in value") - - value, sig = signed_value.rsplit(self.sep, 1) - - if self.verify_signature(value, sig): - return value - - raise BadSignature(f"Signature {sig!r} does not match", payload=value) - - def validate(self, signed_value: str | bytes) -> bool: - """Only validates the given signed value. Returns ``True`` if - the signature exists and is valid. - """ - try: - self.unsign(signed_value) - return True - except BadSignature: - return False diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/timed.py b/serverenv/lib/python3.9/site-packages/itsdangerous/timed.py deleted file mode 100644 index 7384375..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/timed.py +++ /dev/null @@ -1,228 +0,0 @@ -from __future__ import annotations - -import collections.abc as cabc -import time -import typing as t -from datetime import datetime -from datetime import timezone - -from .encoding import base64_decode -from .encoding import base64_encode -from .encoding import bytes_to_int -from .encoding import int_to_bytes -from .encoding import want_bytes -from .exc import BadSignature -from .exc import BadTimeSignature -from .exc import SignatureExpired -from .serializer import _TSerialized -from .serializer import Serializer -from .signer import Signer - - -class TimestampSigner(Signer): - """Works like the regular :class:`.Signer` but also records the time - of the signing and can be used to expire signatures. The - :meth:`unsign` method can raise :exc:`.SignatureExpired` if the - unsigning failed because the signature is expired. - """ - - def get_timestamp(self) -> int: - """Returns the current timestamp. The function must return an - integer. - """ - return int(time.time()) - - def timestamp_to_datetime(self, ts: int) -> datetime: - """Convert the timestamp from :meth:`get_timestamp` into an - aware :class`datetime.datetime` in UTC. - - .. versionchanged:: 2.0 - The timestamp is returned as a timezone-aware ``datetime`` - in UTC rather than a naive ``datetime`` assumed to be UTC. - """ - return datetime.fromtimestamp(ts, tz=timezone.utc) - - def sign(self, value: str | bytes) -> bytes: - """Signs the given string and also attaches time information.""" - value = want_bytes(value) - timestamp = base64_encode(int_to_bytes(self.get_timestamp())) - sep = want_bytes(self.sep) - value = value + sep + timestamp - return value + sep + self.get_signature(value) - - # Ignore overlapping signatures check, return_timestamp is the only - # parameter that affects the return type. - - @t.overload - def unsign( # type: ignore[overload-overlap] - self, - signed_value: str | bytes, - max_age: int | None = None, - return_timestamp: t.Literal[False] = False, - ) -> bytes: ... - - @t.overload - def unsign( - self, - signed_value: str | bytes, - max_age: int | None = None, - return_timestamp: t.Literal[True] = True, - ) -> tuple[bytes, datetime]: ... - - def unsign( - self, - signed_value: str | bytes, - max_age: int | None = None, - return_timestamp: bool = False, - ) -> tuple[bytes, datetime] | bytes: - """Works like the regular :meth:`.Signer.unsign` but can also - validate the time. See the base docstring of the class for - the general behavior. If ``return_timestamp`` is ``True`` the - timestamp of the signature will be returned as an aware - :class:`datetime.datetime` object in UTC. - - .. versionchanged:: 2.0 - The timestamp is returned as a timezone-aware ``datetime`` - in UTC rather than a naive ``datetime`` assumed to be UTC. - """ - try: - result = super().unsign(signed_value) - sig_error = None - except BadSignature as e: - sig_error = e - result = e.payload or b"" - - sep = want_bytes(self.sep) - - # If there is no timestamp in the result there is something - # seriously wrong. In case there was a signature error, we raise - # that one directly, otherwise we have a weird situation in - # which we shouldn't have come except someone uses a time-based - # serializer on non-timestamp data, so catch that. - if sep not in result: - if sig_error: - raise sig_error - - raise BadTimeSignature("timestamp missing", payload=result) - - value, ts_bytes = result.rsplit(sep, 1) - ts_int: int | None = None - ts_dt: datetime | None = None - - try: - ts_int = bytes_to_int(base64_decode(ts_bytes)) - except Exception: - pass - - # Signature is *not* okay. Raise a proper error now that we have - # split the value and the timestamp. - if sig_error is not None: - if ts_int is not None: - try: - ts_dt = self.timestamp_to_datetime(ts_int) - except (ValueError, OSError, OverflowError) as exc: - # Windows raises OSError - # 32-bit raises OverflowError - raise BadTimeSignature( - "Malformed timestamp", payload=value - ) from exc - - raise BadTimeSignature(str(sig_error), payload=value, date_signed=ts_dt) - - # Signature was okay but the timestamp is actually not there or - # malformed. Should not happen, but we handle it anyway. - if ts_int is None: - raise BadTimeSignature("Malformed timestamp", payload=value) - - # Check timestamp is not older than max_age - if max_age is not None: - age = self.get_timestamp() - ts_int - - if age > max_age: - raise SignatureExpired( - f"Signature age {age} > {max_age} seconds", - payload=value, - date_signed=self.timestamp_to_datetime(ts_int), - ) - - if age < 0: - raise SignatureExpired( - f"Signature age {age} < 0 seconds", - payload=value, - date_signed=self.timestamp_to_datetime(ts_int), - ) - - if return_timestamp: - return value, self.timestamp_to_datetime(ts_int) - - return value - - def validate(self, signed_value: str | bytes, max_age: int | None = None) -> bool: - """Only validates the given signed value. Returns ``True`` if - the signature exists and is valid.""" - try: - self.unsign(signed_value, max_age=max_age) - return True - except BadSignature: - return False - - -class TimedSerializer(Serializer[_TSerialized]): - """Uses :class:`TimestampSigner` instead of the default - :class:`.Signer`. - """ - - default_signer: type[TimestampSigner] = TimestampSigner - - def iter_unsigners( - self, salt: str | bytes | None = None - ) -> cabc.Iterator[TimestampSigner]: - return t.cast("cabc.Iterator[TimestampSigner]", super().iter_unsigners(salt)) - - # TODO: Signature is incompatible because parameters were added - # before salt. - - def loads( # type: ignore[override] - self, - s: str | bytes, - max_age: int | None = None, - return_timestamp: bool = False, - salt: str | bytes | None = None, - ) -> t.Any: - """Reverse of :meth:`dumps`, raises :exc:`.BadSignature` if the - signature validation fails. If a ``max_age`` is provided it will - ensure the signature is not older than that time in seconds. In - case the signature is outdated, :exc:`.SignatureExpired` is - raised. All arguments are forwarded to the signer's - :meth:`~TimestampSigner.unsign` method. - """ - s = want_bytes(s) - last_exception = None - - for signer in self.iter_unsigners(salt): - try: - base64d, timestamp = signer.unsign( - s, max_age=max_age, return_timestamp=True - ) - payload = self.load_payload(base64d) - - if return_timestamp: - return payload, timestamp - - return payload - except SignatureExpired: - # The signature was unsigned successfully but was - # expired. Do not try the next signer. - raise - except BadSignature as err: - last_exception = err - - raise t.cast(BadSignature, last_exception) - - def loads_unsafe( # type: ignore[override] - self, - s: str | bytes, - max_age: int | None = None, - salt: str | bytes | None = None, - ) -> tuple[bool, t.Any]: - return self._loads_unsafe_impl(s, salt, load_kwargs={"max_age": max_age}) diff --git a/serverenv/lib/python3.9/site-packages/itsdangerous/url_safe.py b/serverenv/lib/python3.9/site-packages/itsdangerous/url_safe.py deleted file mode 100644 index 56a0793..0000000 --- a/serverenv/lib/python3.9/site-packages/itsdangerous/url_safe.py +++ /dev/null @@ -1,83 +0,0 @@ -from __future__ import annotations - -import typing as t -import zlib - -from ._json import _CompactJSON -from .encoding import base64_decode -from .encoding import base64_encode -from .exc import BadPayload -from .serializer import _PDataSerializer -from .serializer import Serializer -from .timed import TimedSerializer - - -class URLSafeSerializerMixin(Serializer[str]): - """Mixed in with a regular serializer it will attempt to zlib - compress the string to make it shorter if necessary. It will also - base64 encode the string so that it can safely be placed in a URL. - """ - - default_serializer: _PDataSerializer[str] = _CompactJSON - - def load_payload( - self, - payload: bytes, - *args: t.Any, - serializer: t.Any | None = None, - **kwargs: t.Any, - ) -> t.Any: - decompress = False - - if payload.startswith(b"."): - payload = payload[1:] - decompress = True - - try: - json = base64_decode(payload) - except Exception as e: - raise BadPayload( - "Could not base64 decode the payload because of an exception", - original_error=e, - ) from e - - if decompress: - try: - json = zlib.decompress(json) - except Exception as e: - raise BadPayload( - "Could not zlib decompress the payload before decoding the payload", - original_error=e, - ) from e - - return super().load_payload(json, *args, **kwargs) - - def dump_payload(self, obj: t.Any) -> bytes: - json = super().dump_payload(obj) - is_compressed = False - compressed = zlib.compress(json) - - if len(compressed) < (len(json) - 1): - json = compressed - is_compressed = True - - base64d = base64_encode(json) - - if is_compressed: - base64d = b"." + base64d - - return base64d - - -class URLSafeSerializer(URLSafeSerializerMixin, Serializer[str]): - """Works like :class:`.Serializer` but dumps and loads into a URL - safe string consisting of the upper and lowercase character of the - alphabet as well as ``'_'``, ``'-'`` and ``'.'``. - """ - - -class URLSafeTimedSerializer(URLSafeSerializerMixin, TimedSerializer[str]): - """Works like :class:`.TimedSerializer` but dumps and loads into a - URL safe string consisting of the upper and lowercase character of - the alphabet as well as ``'_'``, ``'-'`` and ``'.'``. - """ diff --git a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/INSTALLER b/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/METADATA b/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/METADATA deleted file mode 100644 index ffef2ff..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/METADATA +++ /dev/null @@ -1,84 +0,0 @@ -Metadata-Version: 2.4 -Name: Jinja2 -Version: 3.1.6 -Summary: A very fast and expressive template engine. -Maintainer-email: Pallets -Requires-Python: >=3.7 -Description-Content-Type: text/markdown -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Text Processing :: Markup :: HTML -Classifier: Typing :: Typed -License-File: LICENSE.txt -Requires-Dist: MarkupSafe>=2.0 -Requires-Dist: Babel>=2.7 ; extra == "i18n" -Project-URL: Changes, https://jinja.palletsprojects.com/changes/ -Project-URL: Chat, https://discord.gg/pallets -Project-URL: Documentation, https://jinja.palletsprojects.com/ -Project-URL: Donate, https://palletsprojects.com/donate -Project-URL: Source, https://github.com/pallets/jinja/ -Provides-Extra: i18n - -# Jinja - -Jinja is a fast, expressive, extensible templating engine. Special -placeholders in the template allow writing code similar to Python -syntax. Then the template is passed data to render the final document. - -It includes: - -- Template inheritance and inclusion. -- Define and import macros within templates. -- HTML templates can use autoescaping to prevent XSS from untrusted - user input. -- A sandboxed environment can safely render untrusted templates. -- AsyncIO support for generating templates and calling async - functions. -- I18N support with Babel. -- Templates are compiled to optimized Python code just-in-time and - cached, or can be compiled ahead-of-time. -- Exceptions point to the correct line in templates to make debugging - easier. -- Extensible filters, tests, functions, and even syntax. - -Jinja's philosophy is that while application logic belongs in Python if -possible, it shouldn't make the template designer's job difficult by -restricting functionality too much. - - -## In A Nutshell - -```jinja -{% extends "base.html" %} -{% block title %}Members{% endblock %} -{% block content %} - -{% endblock %} -``` - -## Donate - -The Pallets organization develops and supports Jinja and other popular -packages. In order to grow the community of contributors and users, and -allow the maintainers to devote more time to the projects, [please -donate today][]. - -[please donate today]: https://palletsprojects.com/donate - -## Contributing - -See our [detailed contributing documentation][contrib] for many ways to -contribute, including reporting issues, requesting features, asking or answering -questions, and making PRs. - -[contrib]: https://palletsprojects.com/contributing/ - diff --git a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/RECORD b/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/RECORD deleted file mode 100644 index 5cbc1de..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/RECORD +++ /dev/null @@ -1,57 +0,0 @@ -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/__init__.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/_identifier.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/async_utils.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/bccache.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/compiler.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/constants.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/debug.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/defaults.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/environment.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/exceptions.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/ext.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/filters.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/idtracking.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/lexer.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/loaders.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/meta.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/nativetypes.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/nodes.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/optimizer.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/parser.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/runtime.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/sandbox.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/tests.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/utils.cpython-39.pyc,, -../../../../../../../../Library/Caches/com.apple.python/Users/praveenkumarpalaboyina/Documents/RCTS/c4gt/server/serverenv/lib/python3.9/site-packages/jinja2/visitor.cpython-39.pyc,, -jinja2-3.1.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -jinja2-3.1.6.dist-info/METADATA,sha256=aMVUj7Z8QTKhOJjZsx7FDGvqKr3ZFdkh8hQ1XDpkmcg,2871 -jinja2-3.1.6.dist-info/RECORD,, -jinja2-3.1.6.dist-info/WHEEL,sha256=_2ozNFCLWc93bK4WKHCO-eDUENDlo-dgc9cU3qokYO4,82 -jinja2-3.1.6.dist-info/entry_points.txt,sha256=OL85gYU1eD8cuPlikifFngXpeBjaxl6rIJ8KkC_3r-I,58 -jinja2-3.1.6.dist-info/licenses/LICENSE.txt,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 -jinja2/__init__.py,sha256=xxepO9i7DHsqkQrgBEduLtfoz2QCuT6_gbL4XSN1hbU,1928 -jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 -jinja2/async_utils.py,sha256=vK-PdsuorOMnWSnEkT3iUJRIkTnYgO2T6MnGxDgHI5o,2834 -jinja2/bccache.py,sha256=gh0qs9rulnXo0PhX5jTJy2UHzI8wFnQ63o_vw7nhzRg,14061 -jinja2/compiler.py,sha256=9RpCQl5X88BHllJiPsHPh295Hh0uApvwFJNQuutULeM,74131 -jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 -jinja2/debug.py,sha256=CnHqCDHd-BVGvti_8ZsTolnXNhA3ECsY-6n_2pwU8Hw,6297 -jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 -jinja2/environment.py,sha256=9nhrP7Ch-NbGX00wvyr4yy-uhNHq2OCc60ggGrni_fk,61513 -jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 -jinja2/ext.py,sha256=5PF5eHfh8mXAIxXHHRB2xXbXohi8pE3nHSOxa66uS7E,31875 -jinja2/filters.py,sha256=PQ_Egd9n9jSgtnGQYyF4K5j2nYwhUIulhPnyimkdr-k,55212 -jinja2/idtracking.py,sha256=-ll5lIp73pML3ErUYiIJj7tdmWxcH_IlDv3yA_hiZYo,10555 -jinja2/lexer.py,sha256=LYiYio6br-Tep9nPcupWXsPEtjluw3p1mU-lNBVRUfk,29786 -jinja2/loaders.py,sha256=wIrnxjvcbqh5VwW28NSkfotiDq8qNCxIOSFbGUiSLB4,24055 -jinja2/meta.py,sha256=OTDPkaFvU2Hgvx-6akz7154F8BIWaRmvJcBFvwopHww,4397 -jinja2/nativetypes.py,sha256=7GIGALVJgdyL80oZJdQUaUfwSt5q2lSSZbXt0dNf_M4,4210 -jinja2/nodes.py,sha256=m1Duzcr6qhZI8JQ6VyJgUNinjAf5bQzijSmDnMsvUx8,34579 -jinja2/optimizer.py,sha256=rJnCRlQ7pZsEEmMhsQDgC_pKyDHxP5TPS6zVPGsgcu8,1651 -jinja2/parser.py,sha256=lLOFy3sEmHc5IaEHRiH1sQVnId2moUQzhyeJZTtdY30,40383 -jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -jinja2/runtime.py,sha256=gDk-GvdriJXqgsGbHgrcKTP0Yp6zPXzhzrIpCFH3jAU,34249 -jinja2/sandbox.py,sha256=Mw2aitlY2I8la7FYhcX2YG9BtUYcLnD0Gh3d29cDWrY,15009 -jinja2/tests.py,sha256=VLsBhVFnWg-PxSBz1MhRnNWgP1ovXk3neO1FLQMeC9Q,5926 -jinja2/utils.py,sha256=rRp3o9e7ZKS4fyrWRbELyLcpuGVTFcnooaOa1qx_FIk,24129 -jinja2/visitor.py,sha256=EcnL1PIwf_4RVCOMxsRNuR8AXHbS1qfAdMOE2ngKJz4,3557 diff --git a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/WHEEL b/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/WHEEL deleted file mode 100644 index 23d2d7e..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.11.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/entry_points.txt b/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/entry_points.txt deleted file mode 100644 index abc3eae..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[babel.extractors] -jinja2=jinja2.ext:babel_extract[i18n] - diff --git a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt b/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt deleted file mode 100644 index c37cae4..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2007 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/serverenv/lib/python3.9/site-packages/jinja2/__init__.py b/serverenv/lib/python3.9/site-packages/jinja2/__init__.py deleted file mode 100644 index 1a423a3..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/__init__.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Jinja is a template engine written in pure Python. It provides a -non-XML syntax that supports inline expressions and an optional -sandboxed environment. -""" - -from .bccache import BytecodeCache as BytecodeCache -from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache -from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache -from .environment import Environment as Environment -from .environment import Template as Template -from .exceptions import TemplateAssertionError as TemplateAssertionError -from .exceptions import TemplateError as TemplateError -from .exceptions import TemplateNotFound as TemplateNotFound -from .exceptions import TemplateRuntimeError as TemplateRuntimeError -from .exceptions import TemplatesNotFound as TemplatesNotFound -from .exceptions import TemplateSyntaxError as TemplateSyntaxError -from .exceptions import UndefinedError as UndefinedError -from .loaders import BaseLoader as BaseLoader -from .loaders import ChoiceLoader as ChoiceLoader -from .loaders import DictLoader as DictLoader -from .loaders import FileSystemLoader as FileSystemLoader -from .loaders import FunctionLoader as FunctionLoader -from .loaders import ModuleLoader as ModuleLoader -from .loaders import PackageLoader as PackageLoader -from .loaders import PrefixLoader as PrefixLoader -from .runtime import ChainableUndefined as ChainableUndefined -from .runtime import DebugUndefined as DebugUndefined -from .runtime import make_logging_undefined as make_logging_undefined -from .runtime import StrictUndefined as StrictUndefined -from .runtime import Undefined as Undefined -from .utils import clear_caches as clear_caches -from .utils import is_undefined as is_undefined -from .utils import pass_context as pass_context -from .utils import pass_environment as pass_environment -from .utils import pass_eval_context as pass_eval_context -from .utils import select_autoescape as select_autoescape - -__version__ = "3.1.6" diff --git a/serverenv/lib/python3.9/site-packages/jinja2/_identifier.py b/serverenv/lib/python3.9/site-packages/jinja2/_identifier.py deleted file mode 100644 index 928c150..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/_identifier.py +++ /dev/null @@ -1,6 +0,0 @@ -import re - -# generated by scripts/generate_identifier_pattern.py -pattern = re.compile( - r"[\w·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߽߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛࣓-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣ৾ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣૺ-૿ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఄా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഀ-ഃ഻഼ാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳷-᳹᷀-᷹᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꣿꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𐴤-𐽆𐴧-𐽐𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑄴𑅅𑅆𑅳𑆀-𑆂𑆳-𑇀𑇉-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌻𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑑞𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑠬-𑠺𑨁-𑨊𑨳-𑨹𑨻-𑨾𑩇𑩑-𑩛𑪊-𑪙𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𑴱-𑴶𑴺𑴼𑴽𑴿-𑵅𑵇𑶊-𑶎𑶐𑶑𑶓-𑶗𑻳-𑻶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯]+" # noqa: B950 -) diff --git a/serverenv/lib/python3.9/site-packages/jinja2/async_utils.py b/serverenv/lib/python3.9/site-packages/jinja2/async_utils.py deleted file mode 100644 index f0c1402..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/async_utils.py +++ /dev/null @@ -1,99 +0,0 @@ -import inspect -import typing as t -from functools import WRAPPER_ASSIGNMENTS -from functools import wraps - -from .utils import _PassArg -from .utils import pass_eval_context - -if t.TYPE_CHECKING: - import typing_extensions as te - -V = t.TypeVar("V") - - -def async_variant(normal_func): # type: ignore - def decorator(async_func): # type: ignore - pass_arg = _PassArg.from_obj(normal_func) - need_eval_context = pass_arg is None - - if pass_arg is _PassArg.environment: - - def is_async(args: t.Any) -> bool: - return t.cast(bool, args[0].is_async) - - else: - - def is_async(args: t.Any) -> bool: - return t.cast(bool, args[0].environment.is_async) - - # Take the doc and annotations from the sync function, but the - # name from the async function. Pallets-Sphinx-Themes - # build_function_directive expects __wrapped__ to point to the - # sync function. - async_func_attrs = ("__module__", "__name__", "__qualname__") - normal_func_attrs = tuple(set(WRAPPER_ASSIGNMENTS).difference(async_func_attrs)) - - @wraps(normal_func, assigned=normal_func_attrs) - @wraps(async_func, assigned=async_func_attrs, updated=()) - def wrapper(*args, **kwargs): # type: ignore - b = is_async(args) - - if need_eval_context: - args = args[1:] - - if b: - return async_func(*args, **kwargs) - - return normal_func(*args, **kwargs) - - if need_eval_context: - wrapper = pass_eval_context(wrapper) - - wrapper.jinja_async_variant = True # type: ignore[attr-defined] - return wrapper - - return decorator - - -_common_primitives = {int, float, bool, str, list, dict, tuple, type(None)} - - -async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V": - # Avoid a costly call to isawaitable - if type(value) in _common_primitives: - return t.cast("V", value) - - if inspect.isawaitable(value): - return await t.cast("t.Awaitable[V]", value) - - return value - - -class _IteratorToAsyncIterator(t.Generic[V]): - def __init__(self, iterator: "t.Iterator[V]"): - self._iterator = iterator - - def __aiter__(self) -> "te.Self": - return self - - async def __anext__(self) -> V: - try: - return next(self._iterator) - except StopIteration as e: - raise StopAsyncIteration(e.value) from e - - -def auto_aiter( - iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", -) -> "t.AsyncIterator[V]": - if hasattr(iterable, "__aiter__"): - return iterable.__aiter__() - else: - return _IteratorToAsyncIterator(iter(iterable)) - - -async def auto_to_list( - value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", -) -> t.List["V"]: - return [x async for x in auto_aiter(value)] diff --git a/serverenv/lib/python3.9/site-packages/jinja2/bccache.py b/serverenv/lib/python3.9/site-packages/jinja2/bccache.py deleted file mode 100644 index ada8b09..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/bccache.py +++ /dev/null @@ -1,408 +0,0 @@ -"""The optional bytecode cache system. This is useful if you have very -complex template situations and the compilation of all those templates -slows down your application too much. - -Situations where this is useful are often forking web applications that -are initialized on the first request. -""" - -import errno -import fnmatch -import marshal -import os -import pickle -import stat -import sys -import tempfile -import typing as t -from hashlib import sha1 -from io import BytesIO -from types import CodeType - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .environment import Environment - - class _MemcachedClient(te.Protocol): - def get(self, key: str) -> bytes: ... - - def set( - self, key: str, value: bytes, timeout: t.Optional[int] = None - ) -> None: ... - - -bc_version = 5 -# Magic bytes to identify Jinja bytecode cache files. Contains the -# Python major and minor version to avoid loading incompatible bytecode -# if a project upgrades its Python version. -bc_magic = ( - b"j2" - + pickle.dumps(bc_version, 2) - + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2) -) - - -class Bucket: - """Buckets are used to store the bytecode for one template. It's created - and initialized by the bytecode cache and passed to the loading functions. - - The buckets get an internal checksum from the cache assigned and use this - to automatically reject outdated cache material. Individual bytecode - cache subclasses don't have to care about cache invalidation. - """ - - def __init__(self, environment: "Environment", key: str, checksum: str) -> None: - self.environment = environment - self.key = key - self.checksum = checksum - self.reset() - - def reset(self) -> None: - """Resets the bucket (unloads the bytecode).""" - self.code: t.Optional[CodeType] = None - - def load_bytecode(self, f: t.BinaryIO) -> None: - """Loads bytecode from a file or file like object.""" - # make sure the magic header is correct - magic = f.read(len(bc_magic)) - if magic != bc_magic: - self.reset() - return - # the source code of the file changed, we need to reload - checksum = pickle.load(f) - if self.checksum != checksum: - self.reset() - return - # if marshal_load fails then we need to reload - try: - self.code = marshal.load(f) - except (EOFError, ValueError, TypeError): - self.reset() - return - - def write_bytecode(self, f: t.IO[bytes]) -> None: - """Dump the bytecode into the file or file like object passed.""" - if self.code is None: - raise TypeError("can't write empty bucket") - f.write(bc_magic) - pickle.dump(self.checksum, f, 2) - marshal.dump(self.code, f) - - def bytecode_from_string(self, string: bytes) -> None: - """Load bytecode from bytes.""" - self.load_bytecode(BytesIO(string)) - - def bytecode_to_string(self) -> bytes: - """Return the bytecode as bytes.""" - out = BytesIO() - self.write_bytecode(out) - return out.getvalue() - - -class BytecodeCache: - """To implement your own bytecode cache you have to subclass this class - and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of - these methods are passed a :class:`~jinja2.bccache.Bucket`. - - A very basic bytecode cache that saves the bytecode on the file system:: - - from os import path - - class MyCache(BytecodeCache): - - def __init__(self, directory): - self.directory = directory - - def load_bytecode(self, bucket): - filename = path.join(self.directory, bucket.key) - if path.exists(filename): - with open(filename, 'rb') as f: - bucket.load_bytecode(f) - - def dump_bytecode(self, bucket): - filename = path.join(self.directory, bucket.key) - with open(filename, 'wb') as f: - bucket.write_bytecode(f) - - A more advanced version of a filesystem based bytecode cache is part of - Jinja. - """ - - def load_bytecode(self, bucket: Bucket) -> None: - """Subclasses have to override this method to load bytecode into a - bucket. If they are not able to find code in the cache for the - bucket, it must not do anything. - """ - raise NotImplementedError() - - def dump_bytecode(self, bucket: Bucket) -> None: - """Subclasses have to override this method to write the bytecode - from a bucket back to the cache. If it unable to do so it must not - fail silently but raise an exception. - """ - raise NotImplementedError() - - def clear(self) -> None: - """Clears the cache. This method is not used by Jinja but should be - implemented to allow applications to clear the bytecode cache used - by a particular environment. - """ - - def get_cache_key( - self, name: str, filename: t.Optional[t.Union[str]] = None - ) -> str: - """Returns the unique hash key for this template name.""" - hash = sha1(name.encode("utf-8")) - - if filename is not None: - hash.update(f"|{filename}".encode()) - - return hash.hexdigest() - - def get_source_checksum(self, source: str) -> str: - """Returns a checksum for the source.""" - return sha1(source.encode("utf-8")).hexdigest() - - def get_bucket( - self, - environment: "Environment", - name: str, - filename: t.Optional[str], - source: str, - ) -> Bucket: - """Return a cache bucket for the given template. All arguments are - mandatory but filename may be `None`. - """ - key = self.get_cache_key(name, filename) - checksum = self.get_source_checksum(source) - bucket = Bucket(environment, key, checksum) - self.load_bytecode(bucket) - return bucket - - def set_bucket(self, bucket: Bucket) -> None: - """Put the bucket into the cache.""" - self.dump_bytecode(bucket) - - -class FileSystemBytecodeCache(BytecodeCache): - """A bytecode cache that stores bytecode on the filesystem. It accepts - two arguments: The directory where the cache items are stored and a - pattern string that is used to build the filename. - - If no directory is specified a default cache directory is selected. On - Windows the user's temp directory is used, on UNIX systems a directory - is created for the user in the system temp directory. - - The pattern can be used to have multiple separate caches operate on the - same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` - is replaced with the cache key. - - >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') - - This bytecode cache supports clearing of the cache using the clear method. - """ - - def __init__( - self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache" - ) -> None: - if directory is None: - directory = self._get_default_cache_dir() - self.directory = directory - self.pattern = pattern - - def _get_default_cache_dir(self) -> str: - def _unsafe_dir() -> "te.NoReturn": - raise RuntimeError( - "Cannot determine safe temp directory. You " - "need to explicitly provide one." - ) - - tmpdir = tempfile.gettempdir() - - # On windows the temporary directory is used specific unless - # explicitly forced otherwise. We can just use that. - if os.name == "nt": - return tmpdir - if not hasattr(os, "getuid"): - _unsafe_dir() - - dirname = f"_jinja2-cache-{os.getuid()}" - actual_dir = os.path.join(tmpdir, dirname) - - try: - os.mkdir(actual_dir, stat.S_IRWXU) - except OSError as e: - if e.errno != errno.EEXIST: - raise - try: - os.chmod(actual_dir, stat.S_IRWXU) - actual_dir_stat = os.lstat(actual_dir) - if ( - actual_dir_stat.st_uid != os.getuid() - or not stat.S_ISDIR(actual_dir_stat.st_mode) - or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU - ): - _unsafe_dir() - except OSError as e: - if e.errno != errno.EEXIST: - raise - - actual_dir_stat = os.lstat(actual_dir) - if ( - actual_dir_stat.st_uid != os.getuid() - or not stat.S_ISDIR(actual_dir_stat.st_mode) - or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU - ): - _unsafe_dir() - - return actual_dir - - def _get_cache_filename(self, bucket: Bucket) -> str: - return os.path.join(self.directory, self.pattern % (bucket.key,)) - - def load_bytecode(self, bucket: Bucket) -> None: - filename = self._get_cache_filename(bucket) - - # Don't test for existence before opening the file, since the - # file could disappear after the test before the open. - try: - f = open(filename, "rb") - except (FileNotFoundError, IsADirectoryError, PermissionError): - # PermissionError can occur on Windows when an operation is - # in progress, such as calling clear(). - return - - with f: - bucket.load_bytecode(f) - - def dump_bytecode(self, bucket: Bucket) -> None: - # Write to a temporary file, then rename to the real name after - # writing. This avoids another process reading the file before - # it is fully written. - name = self._get_cache_filename(bucket) - f = tempfile.NamedTemporaryFile( - mode="wb", - dir=os.path.dirname(name), - prefix=os.path.basename(name), - suffix=".tmp", - delete=False, - ) - - def remove_silent() -> None: - try: - os.remove(f.name) - except OSError: - # Another process may have called clear(). On Windows, - # another program may be holding the file open. - pass - - try: - with f: - bucket.write_bytecode(f) - except BaseException: - remove_silent() - raise - - try: - os.replace(f.name, name) - except OSError: - # Another process may have called clear(). On Windows, - # another program may be holding the file open. - remove_silent() - except BaseException: - remove_silent() - raise - - def clear(self) -> None: - # imported lazily here because google app-engine doesn't support - # write access on the file system and the function does not exist - # normally. - from os import remove - - files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",)) - for filename in files: - try: - remove(os.path.join(self.directory, filename)) - except OSError: - pass - - -class MemcachedBytecodeCache(BytecodeCache): - """This class implements a bytecode cache that uses a memcache cache for - storing the information. It does not enforce a specific memcache library - (tummy's memcache or cmemcache) but will accept any class that provides - the minimal interface required. - - Libraries compatible with this class: - - - `cachelib `_ - - `python-memcached `_ - - (Unfortunately the django cache interface is not compatible because it - does not support storing binary data, only text. You can however pass - the underlying cache client to the bytecode cache which is available - as `django.core.cache.cache._client`.) - - The minimal interface for the client passed to the constructor is this: - - .. class:: MinimalClientInterface - - .. method:: set(key, value[, timeout]) - - Stores the bytecode in the cache. `value` is a string and - `timeout` the timeout of the key. If timeout is not provided - a default timeout or no timeout should be assumed, if it's - provided it's an integer with the number of seconds the cache - item should exist. - - .. method:: get(key) - - Returns the value for the cache key. If the item does not - exist in the cache the return value must be `None`. - - The other arguments to the constructor are the prefix for all keys that - is added before the actual cache key and the timeout for the bytecode in - the cache system. We recommend a high (or no) timeout. - - This bytecode cache does not support clearing of used items in the cache. - The clear method is a no-operation function. - - .. versionadded:: 2.7 - Added support for ignoring memcache errors through the - `ignore_memcache_errors` parameter. - """ - - def __init__( - self, - client: "_MemcachedClient", - prefix: str = "jinja2/bytecode/", - timeout: t.Optional[int] = None, - ignore_memcache_errors: bool = True, - ): - self.client = client - self.prefix = prefix - self.timeout = timeout - self.ignore_memcache_errors = ignore_memcache_errors - - def load_bytecode(self, bucket: Bucket) -> None: - try: - code = self.client.get(self.prefix + bucket.key) - except Exception: - if not self.ignore_memcache_errors: - raise - else: - bucket.bytecode_from_string(code) - - def dump_bytecode(self, bucket: Bucket) -> None: - key = self.prefix + bucket.key - value = bucket.bytecode_to_string() - - try: - if self.timeout is not None: - self.client.set(key, value, self.timeout) - else: - self.client.set(key, value) - except Exception: - if not self.ignore_memcache_errors: - raise diff --git a/serverenv/lib/python3.9/site-packages/jinja2/compiler.py b/serverenv/lib/python3.9/site-packages/jinja2/compiler.py deleted file mode 100644 index a4ff6a1..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/compiler.py +++ /dev/null @@ -1,1998 +0,0 @@ -"""Compiles nodes from the parser into Python code.""" - -import typing as t -from contextlib import contextmanager -from functools import update_wrapper -from io import StringIO -from itertools import chain -from keyword import iskeyword as is_python_keyword - -from markupsafe import escape -from markupsafe import Markup - -from . import nodes -from .exceptions import TemplateAssertionError -from .idtracking import Symbols -from .idtracking import VAR_LOAD_ALIAS -from .idtracking import VAR_LOAD_PARAMETER -from .idtracking import VAR_LOAD_RESOLVE -from .idtracking import VAR_LOAD_UNDEFINED -from .nodes import EvalContext -from .optimizer import Optimizer -from .utils import _PassArg -from .utils import concat -from .visitor import NodeVisitor - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .environment import Environment - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) - -operators = { - "eq": "==", - "ne": "!=", - "gt": ">", - "gteq": ">=", - "lt": "<", - "lteq": "<=", - "in": "in", - "notin": "not in", -} - - -def optimizeconst(f: F) -> F: - def new_func( - self: "CodeGenerator", node: nodes.Expr, frame: "Frame", **kwargs: t.Any - ) -> t.Any: - # Only optimize if the frame is not volatile - if self.optimizer is not None and not frame.eval_ctx.volatile: - new_node = self.optimizer.visit(node, frame.eval_ctx) - - if new_node != node: - return self.visit(new_node, frame) - - return f(self, node, frame, **kwargs) - - return update_wrapper(new_func, f) # type: ignore[return-value] - - -def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]: - @optimizeconst - def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None: - if ( - self.environment.sandboxed and op in self.environment.intercepted_binops # type: ignore - ): - self.write(f"environment.call_binop(context, {op!r}, ") - self.visit(node.left, frame) - self.write(", ") - self.visit(node.right, frame) - else: - self.write("(") - self.visit(node.left, frame) - self.write(f" {op} ") - self.visit(node.right, frame) - - self.write(")") - - return visitor - - -def _make_unop( - op: str, -) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]: - @optimizeconst - def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None: - if ( - self.environment.sandboxed and op in self.environment.intercepted_unops # type: ignore - ): - self.write(f"environment.call_unop(context, {op!r}, ") - self.visit(node.node, frame) - else: - self.write("(" + op) - self.visit(node.node, frame) - - self.write(")") - - return visitor - - -def generate( - node: nodes.Template, - environment: "Environment", - name: t.Optional[str], - filename: t.Optional[str], - stream: t.Optional[t.TextIO] = None, - defer_init: bool = False, - optimized: bool = True, -) -> t.Optional[str]: - """Generate the python source for a node tree.""" - if not isinstance(node, nodes.Template): - raise TypeError("Can't compile non template nodes") - - generator = environment.code_generator_class( - environment, name, filename, stream, defer_init, optimized - ) - generator.visit(node) - - if stream is None: - return generator.stream.getvalue() # type: ignore - - return None - - -def has_safe_repr(value: t.Any) -> bool: - """Does the node have a safe representation?""" - if value is None or value is NotImplemented or value is Ellipsis: - return True - - if type(value) in {bool, int, float, complex, range, str, Markup}: - return True - - if type(value) in {tuple, list, set, frozenset}: - return all(has_safe_repr(v) for v in value) - - if type(value) is dict: # noqa E721 - return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items()) - - return False - - -def find_undeclared( - nodes: t.Iterable[nodes.Node], names: t.Iterable[str] -) -> t.Set[str]: - """Check if the names passed are accessed undeclared. The return value - is a set of all the undeclared names from the sequence of names found. - """ - visitor = UndeclaredNameVisitor(names) - try: - for node in nodes: - visitor.visit(node) - except VisitorExit: - pass - return visitor.undeclared - - -class MacroRef: - def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None: - self.node = node - self.accesses_caller = False - self.accesses_kwargs = False - self.accesses_varargs = False - - -class Frame: - """Holds compile time information for us.""" - - def __init__( - self, - eval_ctx: EvalContext, - parent: t.Optional["Frame"] = None, - level: t.Optional[int] = None, - ) -> None: - self.eval_ctx = eval_ctx - - # the parent of this frame - self.parent = parent - - if parent is None: - self.symbols = Symbols(level=level) - - # in some dynamic inheritance situations the compiler needs to add - # write tests around output statements. - self.require_output_check = False - - # inside some tags we are using a buffer rather than yield statements. - # this for example affects {% filter %} or {% macro %}. If a frame - # is buffered this variable points to the name of the list used as - # buffer. - self.buffer: t.Optional[str] = None - - # the name of the block we're in, otherwise None. - self.block: t.Optional[str] = None - - else: - self.symbols = Symbols(parent.symbols, level=level) - self.require_output_check = parent.require_output_check - self.buffer = parent.buffer - self.block = parent.block - - # a toplevel frame is the root + soft frames such as if conditions. - self.toplevel = False - - # the root frame is basically just the outermost frame, so no if - # conditions. This information is used to optimize inheritance - # situations. - self.rootlevel = False - - # variables set inside of loops and blocks should not affect outer frames, - # but they still needs to be kept track of as part of the active context. - self.loop_frame = False - self.block_frame = False - - # track whether the frame is being used in an if-statement or conditional - # expression as it determines which errors should be raised during runtime - # or compile time. - self.soft_frame = False - - def copy(self) -> "te.Self": - """Create a copy of the current one.""" - rv = object.__new__(self.__class__) - rv.__dict__.update(self.__dict__) - rv.symbols = self.symbols.copy() - return rv - - def inner(self, isolated: bool = False) -> "Frame": - """Return an inner frame.""" - if isolated: - return Frame(self.eval_ctx, level=self.symbols.level + 1) - return Frame(self.eval_ctx, self) - - def soft(self) -> "te.Self": - """Return a soft frame. A soft frame may not be modified as - standalone thing as it shares the resources with the frame it - was created of, but it's not a rootlevel frame any longer. - - This is only used to implement if-statements and conditional - expressions. - """ - rv = self.copy() - rv.rootlevel = False - rv.soft_frame = True - return rv - - __copy__ = copy - - -class VisitorExit(RuntimeError): - """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" - - -class DependencyFinderVisitor(NodeVisitor): - """A visitor that collects filter and test calls.""" - - def __init__(self) -> None: - self.filters: t.Set[str] = set() - self.tests: t.Set[str] = set() - - def visit_Filter(self, node: nodes.Filter) -> None: - self.generic_visit(node) - self.filters.add(node.name) - - def visit_Test(self, node: nodes.Test) -> None: - self.generic_visit(node) - self.tests.add(node.name) - - def visit_Block(self, node: nodes.Block) -> None: - """Stop visiting at blocks.""" - - -class UndeclaredNameVisitor(NodeVisitor): - """A visitor that checks if a name is accessed without being - declared. This is different from the frame visitor as it will - not stop at closure frames. - """ - - def __init__(self, names: t.Iterable[str]) -> None: - self.names = set(names) - self.undeclared: t.Set[str] = set() - - def visit_Name(self, node: nodes.Name) -> None: - if node.ctx == "load" and node.name in self.names: - self.undeclared.add(node.name) - if self.undeclared == self.names: - raise VisitorExit() - else: - self.names.discard(node.name) - - def visit_Block(self, node: nodes.Block) -> None: - """Stop visiting a blocks.""" - - -class CompilerExit(Exception): - """Raised if the compiler encountered a situation where it just - doesn't make sense to further process the code. Any block that - raises such an exception is not further processed. - """ - - -class CodeGenerator(NodeVisitor): - def __init__( - self, - environment: "Environment", - name: t.Optional[str], - filename: t.Optional[str], - stream: t.Optional[t.TextIO] = None, - defer_init: bool = False, - optimized: bool = True, - ) -> None: - if stream is None: - stream = StringIO() - self.environment = environment - self.name = name - self.filename = filename - self.stream = stream - self.created_block_context = False - self.defer_init = defer_init - self.optimizer: t.Optional[Optimizer] = None - - if optimized: - self.optimizer = Optimizer(environment) - - # aliases for imports - self.import_aliases: t.Dict[str, str] = {} - - # a registry for all blocks. Because blocks are moved out - # into the global python scope they are registered here - self.blocks: t.Dict[str, nodes.Block] = {} - - # the number of extends statements so far - self.extends_so_far = 0 - - # some templates have a rootlevel extends. In this case we - # can safely assume that we're a child template and do some - # more optimizations. - self.has_known_extends = False - - # the current line number - self.code_lineno = 1 - - # registry of all filters and tests (global, not block local) - self.tests: t.Dict[str, str] = {} - self.filters: t.Dict[str, str] = {} - - # the debug information - self.debug_info: t.List[t.Tuple[int, int]] = [] - self._write_debug_info: t.Optional[int] = None - - # the number of new lines before the next write() - self._new_lines = 0 - - # the line number of the last written statement - self._last_line = 0 - - # true if nothing was written so far. - self._first_write = True - - # used by the `temporary_identifier` method to get new - # unique, temporary identifier - self._last_identifier = 0 - - # the current indentation - self._indentation = 0 - - # Tracks toplevel assignments - self._assign_stack: t.List[t.Set[str]] = [] - - # Tracks parameter definition blocks - self._param_def_block: t.List[t.Set[str]] = [] - - # Tracks the current context. - self._context_reference_stack = ["context"] - - @property - def optimized(self) -> bool: - return self.optimizer is not None - - # -- Various compilation helpers - - def fail(self, msg: str, lineno: int) -> "te.NoReturn": - """Fail with a :exc:`TemplateAssertionError`.""" - raise TemplateAssertionError(msg, lineno, self.name, self.filename) - - def temporary_identifier(self) -> str: - """Get a new unique identifier.""" - self._last_identifier += 1 - return f"t_{self._last_identifier}" - - def buffer(self, frame: Frame) -> None: - """Enable buffering for the frame from that point onwards.""" - frame.buffer = self.temporary_identifier() - self.writeline(f"{frame.buffer} = []") - - def return_buffer_contents( - self, frame: Frame, force_unescaped: bool = False - ) -> None: - """Return the buffer contents of the frame.""" - if not force_unescaped: - if frame.eval_ctx.volatile: - self.writeline("if context.eval_ctx.autoescape:") - self.indent() - self.writeline(f"return Markup(concat({frame.buffer}))") - self.outdent() - self.writeline("else:") - self.indent() - self.writeline(f"return concat({frame.buffer})") - self.outdent() - return - elif frame.eval_ctx.autoescape: - self.writeline(f"return Markup(concat({frame.buffer}))") - return - self.writeline(f"return concat({frame.buffer})") - - def indent(self) -> None: - """Indent by one.""" - self._indentation += 1 - - def outdent(self, step: int = 1) -> None: - """Outdent by step.""" - self._indentation -= step - - def start_write(self, frame: Frame, node: t.Optional[nodes.Node] = None) -> None: - """Yield or write into the frame buffer.""" - if frame.buffer is None: - self.writeline("yield ", node) - else: - self.writeline(f"{frame.buffer}.append(", node) - - def end_write(self, frame: Frame) -> None: - """End the writing process started by `start_write`.""" - if frame.buffer is not None: - self.write(")") - - def simple_write( - self, s: str, frame: Frame, node: t.Optional[nodes.Node] = None - ) -> None: - """Simple shortcut for start_write + write + end_write.""" - self.start_write(frame, node) - self.write(s) - self.end_write(frame) - - def blockvisit(self, nodes: t.Iterable[nodes.Node], frame: Frame) -> None: - """Visit a list of nodes as block in a frame. If the current frame - is no buffer a dummy ``if 0: yield None`` is written automatically. - """ - try: - self.writeline("pass") - for node in nodes: - self.visit(node, frame) - except CompilerExit: - pass - - def write(self, x: str) -> None: - """Write a string into the output stream.""" - if self._new_lines: - if not self._first_write: - self.stream.write("\n" * self._new_lines) - self.code_lineno += self._new_lines - if self._write_debug_info is not None: - self.debug_info.append((self._write_debug_info, self.code_lineno)) - self._write_debug_info = None - self._first_write = False - self.stream.write(" " * self._indentation) - self._new_lines = 0 - self.stream.write(x) - - def writeline( - self, x: str, node: t.Optional[nodes.Node] = None, extra: int = 0 - ) -> None: - """Combination of newline and write.""" - self.newline(node, extra) - self.write(x) - - def newline(self, node: t.Optional[nodes.Node] = None, extra: int = 0) -> None: - """Add one or more newlines before the next write.""" - self._new_lines = max(self._new_lines, 1 + extra) - if node is not None and node.lineno != self._last_line: - self._write_debug_info = node.lineno - self._last_line = node.lineno - - def signature( - self, - node: t.Union[nodes.Call, nodes.Filter, nodes.Test], - frame: Frame, - extra_kwargs: t.Optional[t.Mapping[str, t.Any]] = None, - ) -> None: - """Writes a function call to the stream for the current node. - A leading comma is added automatically. The extra keyword - arguments may not include python keywords otherwise a syntax - error could occur. The extra keyword arguments should be given - as python dict. - """ - # if any of the given keyword arguments is a python keyword - # we have to make sure that no invalid call is created. - kwarg_workaround = any( - is_python_keyword(t.cast(str, k)) - for k in chain((x.key for x in node.kwargs), extra_kwargs or ()) - ) - - for arg in node.args: - self.write(", ") - self.visit(arg, frame) - - if not kwarg_workaround: - for kwarg in node.kwargs: - self.write(", ") - self.visit(kwarg, frame) - if extra_kwargs is not None: - for key, value in extra_kwargs.items(): - self.write(f", {key}={value}") - if node.dyn_args: - self.write(", *") - self.visit(node.dyn_args, frame) - - if kwarg_workaround: - if node.dyn_kwargs is not None: - self.write(", **dict({") - else: - self.write(", **{") - for kwarg in node.kwargs: - self.write(f"{kwarg.key!r}: ") - self.visit(kwarg.value, frame) - self.write(", ") - if extra_kwargs is not None: - for key, value in extra_kwargs.items(): - self.write(f"{key!r}: {value}, ") - if node.dyn_kwargs is not None: - self.write("}, **") - self.visit(node.dyn_kwargs, frame) - self.write(")") - else: - self.write("}") - - elif node.dyn_kwargs is not None: - self.write(", **") - self.visit(node.dyn_kwargs, frame) - - def pull_dependencies(self, nodes: t.Iterable[nodes.Node]) -> None: - """Find all filter and test names used in the template and - assign them to variables in the compiled namespace. Checking - that the names are registered with the environment is done when - compiling the Filter and Test nodes. If the node is in an If or - CondExpr node, the check is done at runtime instead. - - .. versionchanged:: 3.0 - Filters and tests in If and CondExpr nodes are checked at - runtime instead of compile time. - """ - visitor = DependencyFinderVisitor() - - for node in nodes: - visitor.visit(node) - - for id_map, names, dependency in ( - (self.filters, visitor.filters, "filters"), - ( - self.tests, - visitor.tests, - "tests", - ), - ): - for name in sorted(names): - if name not in id_map: - id_map[name] = self.temporary_identifier() - - # add check during runtime that dependencies used inside of executed - # blocks are defined, as this step may be skipped during compile time - self.writeline("try:") - self.indent() - self.writeline(f"{id_map[name]} = environment.{dependency}[{name!r}]") - self.outdent() - self.writeline("except KeyError:") - self.indent() - self.writeline("@internalcode") - self.writeline(f"def {id_map[name]}(*unused):") - self.indent() - self.writeline( - f'raise TemplateRuntimeError("No {dependency[:-1]}' - f' named {name!r} found.")' - ) - self.outdent() - self.outdent() - - def enter_frame(self, frame: Frame) -> None: - undefs = [] - for target, (action, param) in frame.symbols.loads.items(): - if action == VAR_LOAD_PARAMETER: - pass - elif action == VAR_LOAD_RESOLVE: - self.writeline(f"{target} = {self.get_resolve_func()}({param!r})") - elif action == VAR_LOAD_ALIAS: - self.writeline(f"{target} = {param}") - elif action == VAR_LOAD_UNDEFINED: - undefs.append(target) - else: - raise NotImplementedError("unknown load instruction") - if undefs: - self.writeline(f"{' = '.join(undefs)} = missing") - - def leave_frame(self, frame: Frame, with_python_scope: bool = False) -> None: - if not with_python_scope: - undefs = [] - for target in frame.symbols.loads: - undefs.append(target) - if undefs: - self.writeline(f"{' = '.join(undefs)} = missing") - - def choose_async(self, async_value: str = "async ", sync_value: str = "") -> str: - return async_value if self.environment.is_async else sync_value - - def func(self, name: str) -> str: - return f"{self.choose_async()}def {name}" - - def macro_body( - self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame - ) -> t.Tuple[Frame, MacroRef]: - """Dump the function def of a macro or call block.""" - frame = frame.inner() - frame.symbols.analyze_node(node) - macro_ref = MacroRef(node) - - explicit_caller = None - skip_special_params = set() - args = [] - - for idx, arg in enumerate(node.args): - if arg.name == "caller": - explicit_caller = idx - if arg.name in ("kwargs", "varargs"): - skip_special_params.add(arg.name) - args.append(frame.symbols.ref(arg.name)) - - undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs")) - - if "caller" in undeclared: - # In older Jinja versions there was a bug that allowed caller - # to retain the special behavior even if it was mentioned in - # the argument list. However thankfully this was only really - # working if it was the last argument. So we are explicitly - # checking this now and error out if it is anywhere else in - # the argument list. - if explicit_caller is not None: - try: - node.defaults[explicit_caller - len(node.args)] - except IndexError: - self.fail( - "When defining macros or call blocks the " - 'special "caller" argument must be omitted ' - "or be given a default.", - node.lineno, - ) - else: - args.append(frame.symbols.declare_parameter("caller")) - macro_ref.accesses_caller = True - if "kwargs" in undeclared and "kwargs" not in skip_special_params: - args.append(frame.symbols.declare_parameter("kwargs")) - macro_ref.accesses_kwargs = True - if "varargs" in undeclared and "varargs" not in skip_special_params: - args.append(frame.symbols.declare_parameter("varargs")) - macro_ref.accesses_varargs = True - - # macros are delayed, they never require output checks - frame.require_output_check = False - frame.symbols.analyze_node(node) - self.writeline(f"{self.func('macro')}({', '.join(args)}):", node) - self.indent() - - self.buffer(frame) - self.enter_frame(frame) - - self.push_parameter_definitions(frame) - for idx, arg in enumerate(node.args): - ref = frame.symbols.ref(arg.name) - self.writeline(f"if {ref} is missing:") - self.indent() - try: - default = node.defaults[idx - len(node.args)] - except IndexError: - self.writeline( - f'{ref} = undefined("parameter {arg.name!r} was not provided",' - f" name={arg.name!r})" - ) - else: - self.writeline(f"{ref} = ") - self.visit(default, frame) - self.mark_parameter_stored(ref) - self.outdent() - self.pop_parameter_definitions() - - self.blockvisit(node.body, frame) - self.return_buffer_contents(frame, force_unescaped=True) - self.leave_frame(frame, with_python_scope=True) - self.outdent() - - return frame, macro_ref - - def macro_def(self, macro_ref: MacroRef, frame: Frame) -> None: - """Dump the macro definition for the def created by macro_body.""" - arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args) - name = getattr(macro_ref.node, "name", None) - if len(macro_ref.node.args) == 1: - arg_tuple += "," - self.write( - f"Macro(environment, macro, {name!r}, ({arg_tuple})," - f" {macro_ref.accesses_kwargs!r}, {macro_ref.accesses_varargs!r}," - f" {macro_ref.accesses_caller!r}, context.eval_ctx.autoescape)" - ) - - def position(self, node: nodes.Node) -> str: - """Return a human readable position for the node.""" - rv = f"line {node.lineno}" - if self.name is not None: - rv = f"{rv} in {self.name!r}" - return rv - - def dump_local_context(self, frame: Frame) -> str: - items_kv = ", ".join( - f"{name!r}: {target}" - for name, target in frame.symbols.dump_stores().items() - ) - return f"{{{items_kv}}}" - - def write_commons(self) -> None: - """Writes a common preamble that is used by root and block functions. - Primarily this sets up common local helpers and enforces a generator - through a dead branch. - """ - self.writeline("resolve = context.resolve_or_missing") - self.writeline("undefined = environment.undefined") - self.writeline("concat = environment.concat") - # always use the standard Undefined class for the implicit else of - # conditional expressions - self.writeline("cond_expr_undefined = Undefined") - self.writeline("if 0: yield None") - - def push_parameter_definitions(self, frame: Frame) -> None: - """Pushes all parameter targets from the given frame into a local - stack that permits tracking of yet to be assigned parameters. In - particular this enables the optimization from `visit_Name` to skip - undefined expressions for parameters in macros as macros can reference - otherwise unbound parameters. - """ - self._param_def_block.append(frame.symbols.dump_param_targets()) - - def pop_parameter_definitions(self) -> None: - """Pops the current parameter definitions set.""" - self._param_def_block.pop() - - def mark_parameter_stored(self, target: str) -> None: - """Marks a parameter in the current parameter definitions as stored. - This will skip the enforced undefined checks. - """ - if self._param_def_block: - self._param_def_block[-1].discard(target) - - def push_context_reference(self, target: str) -> None: - self._context_reference_stack.append(target) - - def pop_context_reference(self) -> None: - self._context_reference_stack.pop() - - def get_context_ref(self) -> str: - return self._context_reference_stack[-1] - - def get_resolve_func(self) -> str: - target = self._context_reference_stack[-1] - if target == "context": - return "resolve" - return f"{target}.resolve" - - def derive_context(self, frame: Frame) -> str: - return f"{self.get_context_ref()}.derived({self.dump_local_context(frame)})" - - def parameter_is_undeclared(self, target: str) -> bool: - """Checks if a given target is an undeclared parameter.""" - if not self._param_def_block: - return False - return target in self._param_def_block[-1] - - def push_assign_tracking(self) -> None: - """Pushes a new layer for assignment tracking.""" - self._assign_stack.append(set()) - - def pop_assign_tracking(self, frame: Frame) -> None: - """Pops the topmost level for assignment tracking and updates the - context variables if necessary. - """ - vars = self._assign_stack.pop() - if ( - not frame.block_frame - and not frame.loop_frame - and not frame.toplevel - or not vars - ): - return - public_names = [x for x in vars if x[:1] != "_"] - if len(vars) == 1: - name = next(iter(vars)) - ref = frame.symbols.ref(name) - if frame.loop_frame: - self.writeline(f"_loop_vars[{name!r}] = {ref}") - return - if frame.block_frame: - self.writeline(f"_block_vars[{name!r}] = {ref}") - return - self.writeline(f"context.vars[{name!r}] = {ref}") - else: - if frame.loop_frame: - self.writeline("_loop_vars.update({") - elif frame.block_frame: - self.writeline("_block_vars.update({") - else: - self.writeline("context.vars.update({") - for idx, name in enumerate(sorted(vars)): - if idx: - self.write(", ") - ref = frame.symbols.ref(name) - self.write(f"{name!r}: {ref}") - self.write("})") - if not frame.block_frame and not frame.loop_frame and public_names: - if len(public_names) == 1: - self.writeline(f"context.exported_vars.add({public_names[0]!r})") - else: - names_str = ", ".join(map(repr, sorted(public_names))) - self.writeline(f"context.exported_vars.update(({names_str}))") - - # -- Statement Visitors - - def visit_Template( - self, node: nodes.Template, frame: t.Optional[Frame] = None - ) -> None: - assert frame is None, "no root frame allowed" - eval_ctx = EvalContext(self.environment, self.name) - - from .runtime import async_exported - from .runtime import exported - - if self.environment.is_async: - exported_names = sorted(exported + async_exported) - else: - exported_names = sorted(exported) - - self.writeline("from jinja2.runtime import " + ", ".join(exported_names)) - - # if we want a deferred initialization we cannot move the - # environment into a local name - envenv = "" if self.defer_init else ", environment=environment" - - # do we have an extends tag at all? If not, we can save some - # overhead by just not processing any inheritance code. - have_extends = node.find(nodes.Extends) is not None - - # find all blocks - for block in node.find_all(nodes.Block): - if block.name in self.blocks: - self.fail(f"block {block.name!r} defined twice", block.lineno) - self.blocks[block.name] = block - - # find all imports and import them - for import_ in node.find_all(nodes.ImportedName): - if import_.importname not in self.import_aliases: - imp = import_.importname - self.import_aliases[imp] = alias = self.temporary_identifier() - if "." in imp: - module, obj = imp.rsplit(".", 1) - self.writeline(f"from {module} import {obj} as {alias}") - else: - self.writeline(f"import {imp} as {alias}") - - # add the load name - self.writeline(f"name = {self.name!r}") - - # generate the root render function. - self.writeline( - f"{self.func('root')}(context, missing=missing{envenv}):", extra=1 - ) - self.indent() - self.write_commons() - - # process the root - frame = Frame(eval_ctx) - if "self" in find_undeclared(node.body, ("self",)): - ref = frame.symbols.declare_parameter("self") - self.writeline(f"{ref} = TemplateReference(context)") - frame.symbols.analyze_node(node) - frame.toplevel = frame.rootlevel = True - frame.require_output_check = have_extends and not self.has_known_extends - if have_extends: - self.writeline("parent_template = None") - self.enter_frame(frame) - self.pull_dependencies(node.body) - self.blockvisit(node.body, frame) - self.leave_frame(frame, with_python_scope=True) - self.outdent() - - # make sure that the parent root is called. - if have_extends: - if not self.has_known_extends: - self.indent() - self.writeline("if parent_template is not None:") - self.indent() - if not self.environment.is_async: - self.writeline("yield from parent_template.root_render_func(context)") - else: - self.writeline("agen = parent_template.root_render_func(context)") - self.writeline("try:") - self.indent() - self.writeline("async for event in agen:") - self.indent() - self.writeline("yield event") - self.outdent() - self.outdent() - self.writeline("finally: await agen.aclose()") - self.outdent(1 + (not self.has_known_extends)) - - # at this point we now have the blocks collected and can visit them too. - for name, block in self.blocks.items(): - self.writeline( - f"{self.func('block_' + name)}(context, missing=missing{envenv}):", - block, - 1, - ) - self.indent() - self.write_commons() - # It's important that we do not make this frame a child of the - # toplevel template. This would cause a variety of - # interesting issues with identifier tracking. - block_frame = Frame(eval_ctx) - block_frame.block_frame = True - undeclared = find_undeclared(block.body, ("self", "super")) - if "self" in undeclared: - ref = block_frame.symbols.declare_parameter("self") - self.writeline(f"{ref} = TemplateReference(context)") - if "super" in undeclared: - ref = block_frame.symbols.declare_parameter("super") - self.writeline(f"{ref} = context.super({name!r}, block_{name})") - block_frame.symbols.analyze_node(block) - block_frame.block = name - self.writeline("_block_vars = {}") - self.enter_frame(block_frame) - self.pull_dependencies(block.body) - self.blockvisit(block.body, block_frame) - self.leave_frame(block_frame, with_python_scope=True) - self.outdent() - - blocks_kv_str = ", ".join(f"{x!r}: block_{x}" for x in self.blocks) - self.writeline(f"blocks = {{{blocks_kv_str}}}", extra=1) - debug_kv_str = "&".join(f"{k}={v}" for k, v in self.debug_info) - self.writeline(f"debug_info = {debug_kv_str!r}") - - def visit_Block(self, node: nodes.Block, frame: Frame) -> None: - """Call a block and register it for the template.""" - level = 0 - if frame.toplevel: - # if we know that we are a child template, there is no need to - # check if we are one - if self.has_known_extends: - return - if self.extends_so_far > 0: - self.writeline("if parent_template is None:") - self.indent() - level += 1 - - if node.scoped: - context = self.derive_context(frame) - else: - context = self.get_context_ref() - - if node.required: - self.writeline(f"if len(context.blocks[{node.name!r}]) <= 1:", node) - self.indent() - self.writeline( - f'raise TemplateRuntimeError("Required block {node.name!r} not found")', - node, - ) - self.outdent() - - if not self.environment.is_async and frame.buffer is None: - self.writeline( - f"yield from context.blocks[{node.name!r}][0]({context})", node - ) - else: - self.writeline(f"gen = context.blocks[{node.name!r}][0]({context})") - self.writeline("try:") - self.indent() - self.writeline( - f"{self.choose_async()}for event in gen:", - node, - ) - self.indent() - self.simple_write("event", frame) - self.outdent() - self.outdent() - self.writeline( - f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" - ) - - self.outdent(level) - - def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None: - """Calls the extender.""" - if not frame.toplevel: - self.fail("cannot use extend from a non top-level scope", node.lineno) - - # if the number of extends statements in general is zero so - # far, we don't have to add a check if something extended - # the template before this one. - if self.extends_so_far > 0: - # if we have a known extends we just add a template runtime - # error into the generated code. We could catch that at compile - # time too, but i welcome it not to confuse users by throwing the - # same error at different times just "because we can". - if not self.has_known_extends: - self.writeline("if parent_template is not None:") - self.indent() - self.writeline('raise TemplateRuntimeError("extended multiple times")') - - # if we have a known extends already we don't need that code here - # as we know that the template execution will end here. - if self.has_known_extends: - raise CompilerExit() - else: - self.outdent() - - self.writeline("parent_template = environment.get_template(", node) - self.visit(node.template, frame) - self.write(f", {self.name!r})") - self.writeline("for name, parent_block in parent_template.blocks.items():") - self.indent() - self.writeline("context.blocks.setdefault(name, []).append(parent_block)") - self.outdent() - - # if this extends statement was in the root level we can take - # advantage of that information and simplify the generated code - # in the top level from this point onwards - if frame.rootlevel: - self.has_known_extends = True - - # and now we have one more - self.extends_so_far += 1 - - def visit_Include(self, node: nodes.Include, frame: Frame) -> None: - """Handles includes.""" - if node.ignore_missing: - self.writeline("try:") - self.indent() - - func_name = "get_or_select_template" - if isinstance(node.template, nodes.Const): - if isinstance(node.template.value, str): - func_name = "get_template" - elif isinstance(node.template.value, (tuple, list)): - func_name = "select_template" - elif isinstance(node.template, (nodes.Tuple, nodes.List)): - func_name = "select_template" - - self.writeline(f"template = environment.{func_name}(", node) - self.visit(node.template, frame) - self.write(f", {self.name!r})") - if node.ignore_missing: - self.outdent() - self.writeline("except TemplateNotFound:") - self.indent() - self.writeline("pass") - self.outdent() - self.writeline("else:") - self.indent() - - def loop_body() -> None: - self.indent() - self.simple_write("event", frame) - self.outdent() - - if node.with_context: - self.writeline( - f"gen = template.root_render_func(" - "template.new_context(context.get_all(), True," - f" {self.dump_local_context(frame)}))" - ) - self.writeline("try:") - self.indent() - self.writeline(f"{self.choose_async()}for event in gen:") - loop_body() - self.outdent() - self.writeline( - f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" - ) - elif self.environment.is_async: - self.writeline( - "for event in (await template._get_default_module_async())" - "._body_stream:" - ) - loop_body() - else: - self.writeline("yield from template._get_default_module()._body_stream") - - if node.ignore_missing: - self.outdent() - - def _import_common( - self, node: t.Union[nodes.Import, nodes.FromImport], frame: Frame - ) -> None: - self.write(f"{self.choose_async('await ')}environment.get_template(") - self.visit(node.template, frame) - self.write(f", {self.name!r}).") - - if node.with_context: - f_name = f"make_module{self.choose_async('_async')}" - self.write( - f"{f_name}(context.get_all(), True, {self.dump_local_context(frame)})" - ) - else: - self.write(f"_get_default_module{self.choose_async('_async')}(context)") - - def visit_Import(self, node: nodes.Import, frame: Frame) -> None: - """Visit regular imports.""" - self.writeline(f"{frame.symbols.ref(node.target)} = ", node) - if frame.toplevel: - self.write(f"context.vars[{node.target!r}] = ") - - self._import_common(node, frame) - - if frame.toplevel and not node.target.startswith("_"): - self.writeline(f"context.exported_vars.discard({node.target!r})") - - def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None: - """Visit named imports.""" - self.newline(node) - self.write("included_template = ") - self._import_common(node, frame) - var_names = [] - discarded_names = [] - for name in node.names: - if isinstance(name, tuple): - name, alias = name - else: - alias = name - self.writeline( - f"{frame.symbols.ref(alias)} =" - f" getattr(included_template, {name!r}, missing)" - ) - self.writeline(f"if {frame.symbols.ref(alias)} is missing:") - self.indent() - # The position will contain the template name, and will be formatted - # into a string that will be compiled into an f-string. Curly braces - # in the name must be replaced with escapes so that they will not be - # executed as part of the f-string. - position = self.position(node).replace("{", "{{").replace("}", "}}") - message = ( - "the template {included_template.__name__!r}" - f" (imported on {position})" - f" does not export the requested name {name!r}" - ) - self.writeline( - f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})" - ) - self.outdent() - if frame.toplevel: - var_names.append(alias) - if not alias.startswith("_"): - discarded_names.append(alias) - - if var_names: - if len(var_names) == 1: - name = var_names[0] - self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}") - else: - names_kv = ", ".join( - f"{name!r}: {frame.symbols.ref(name)}" for name in var_names - ) - self.writeline(f"context.vars.update({{{names_kv}}})") - if discarded_names: - if len(discarded_names) == 1: - self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})") - else: - names_str = ", ".join(map(repr, discarded_names)) - self.writeline( - f"context.exported_vars.difference_update(({names_str}))" - ) - - def visit_For(self, node: nodes.For, frame: Frame) -> None: - loop_frame = frame.inner() - loop_frame.loop_frame = True - test_frame = frame.inner() - else_frame = frame.inner() - - # try to figure out if we have an extended loop. An extended loop - # is necessary if the loop is in recursive mode if the special loop - # variable is accessed in the body if the body is a scoped block. - extended_loop = ( - node.recursive - or "loop" - in find_undeclared(node.iter_child_nodes(only=("body",)), ("loop",)) - or any(block.scoped for block in node.find_all(nodes.Block)) - ) - - loop_ref = None - if extended_loop: - loop_ref = loop_frame.symbols.declare_parameter("loop") - - loop_frame.symbols.analyze_node(node, for_branch="body") - if node.else_: - else_frame.symbols.analyze_node(node, for_branch="else") - - if node.test: - loop_filter_func = self.temporary_identifier() - test_frame.symbols.analyze_node(node, for_branch="test") - self.writeline(f"{self.func(loop_filter_func)}(fiter):", node.test) - self.indent() - self.enter_frame(test_frame) - self.writeline(self.choose_async("async for ", "for ")) - self.visit(node.target, loop_frame) - self.write(" in ") - self.write(self.choose_async("auto_aiter(fiter)", "fiter")) - self.write(":") - self.indent() - self.writeline("if ", node.test) - self.visit(node.test, test_frame) - self.write(":") - self.indent() - self.writeline("yield ") - self.visit(node.target, loop_frame) - self.outdent(3) - self.leave_frame(test_frame, with_python_scope=True) - - # if we don't have an recursive loop we have to find the shadowed - # variables at that point. Because loops can be nested but the loop - # variable is a special one we have to enforce aliasing for it. - if node.recursive: - self.writeline( - f"{self.func('loop')}(reciter, loop_render_func, depth=0):", node - ) - self.indent() - self.buffer(loop_frame) - - # Use the same buffer for the else frame - else_frame.buffer = loop_frame.buffer - - # make sure the loop variable is a special one and raise a template - # assertion error if a loop tries to write to loop - if extended_loop: - self.writeline(f"{loop_ref} = missing") - - for name in node.find_all(nodes.Name): - if name.ctx == "store" and name.name == "loop": - self.fail( - "Can't assign to special loop variable in for-loop target", - name.lineno, - ) - - if node.else_: - iteration_indicator = self.temporary_identifier() - self.writeline(f"{iteration_indicator} = 1") - - self.writeline(self.choose_async("async for ", "for "), node) - self.visit(node.target, loop_frame) - if extended_loop: - self.write(f", {loop_ref} in {self.choose_async('Async')}LoopContext(") - else: - self.write(" in ") - - if node.test: - self.write(f"{loop_filter_func}(") - if node.recursive: - self.write("reciter") - else: - if self.environment.is_async and not extended_loop: - self.write("auto_aiter(") - self.visit(node.iter, frame) - if self.environment.is_async and not extended_loop: - self.write(")") - if node.test: - self.write(")") - - if node.recursive: - self.write(", undefined, loop_render_func, depth):") - else: - self.write(", undefined):" if extended_loop else ":") - - self.indent() - self.enter_frame(loop_frame) - - self.writeline("_loop_vars = {}") - self.blockvisit(node.body, loop_frame) - if node.else_: - self.writeline(f"{iteration_indicator} = 0") - self.outdent() - self.leave_frame( - loop_frame, with_python_scope=node.recursive and not node.else_ - ) - - if node.else_: - self.writeline(f"if {iteration_indicator}:") - self.indent() - self.enter_frame(else_frame) - self.blockvisit(node.else_, else_frame) - self.leave_frame(else_frame) - self.outdent() - - # if the node was recursive we have to return the buffer contents - # and start the iteration code - if node.recursive: - self.return_buffer_contents(loop_frame) - self.outdent() - self.start_write(frame, node) - self.write(f"{self.choose_async('await ')}loop(") - if self.environment.is_async: - self.write("auto_aiter(") - self.visit(node.iter, frame) - if self.environment.is_async: - self.write(")") - self.write(", loop)") - self.end_write(frame) - - # at the end of the iteration, clear any assignments made in the - # loop from the top level - if self._assign_stack: - self._assign_stack[-1].difference_update(loop_frame.symbols.stores) - - def visit_If(self, node: nodes.If, frame: Frame) -> None: - if_frame = frame.soft() - self.writeline("if ", node) - self.visit(node.test, if_frame) - self.write(":") - self.indent() - self.blockvisit(node.body, if_frame) - self.outdent() - for elif_ in node.elif_: - self.writeline("elif ", elif_) - self.visit(elif_.test, if_frame) - self.write(":") - self.indent() - self.blockvisit(elif_.body, if_frame) - self.outdent() - if node.else_: - self.writeline("else:") - self.indent() - self.blockvisit(node.else_, if_frame) - self.outdent() - - def visit_Macro(self, node: nodes.Macro, frame: Frame) -> None: - macro_frame, macro_ref = self.macro_body(node, frame) - self.newline() - if frame.toplevel: - if not node.name.startswith("_"): - self.write(f"context.exported_vars.add({node.name!r})") - self.writeline(f"context.vars[{node.name!r}] = ") - self.write(f"{frame.symbols.ref(node.name)} = ") - self.macro_def(macro_ref, macro_frame) - - def visit_CallBlock(self, node: nodes.CallBlock, frame: Frame) -> None: - call_frame, macro_ref = self.macro_body(node, frame) - self.writeline("caller = ") - self.macro_def(macro_ref, call_frame) - self.start_write(frame, node) - self.visit_Call(node.call, frame, forward_caller=True) - self.end_write(frame) - - def visit_FilterBlock(self, node: nodes.FilterBlock, frame: Frame) -> None: - filter_frame = frame.inner() - filter_frame.symbols.analyze_node(node) - self.enter_frame(filter_frame) - self.buffer(filter_frame) - self.blockvisit(node.body, filter_frame) - self.start_write(frame, node) - self.visit_Filter(node.filter, filter_frame) - self.end_write(frame) - self.leave_frame(filter_frame) - - def visit_With(self, node: nodes.With, frame: Frame) -> None: - with_frame = frame.inner() - with_frame.symbols.analyze_node(node) - self.enter_frame(with_frame) - for target, expr in zip(node.targets, node.values): - self.newline() - self.visit(target, with_frame) - self.write(" = ") - self.visit(expr, frame) - self.blockvisit(node.body, with_frame) - self.leave_frame(with_frame) - - def visit_ExprStmt(self, node: nodes.ExprStmt, frame: Frame) -> None: - self.newline(node) - self.visit(node.node, frame) - - class _FinalizeInfo(t.NamedTuple): - const: t.Optional[t.Callable[..., str]] - src: t.Optional[str] - - @staticmethod - def _default_finalize(value: t.Any) -> t.Any: - """The default finalize function if the environment isn't - configured with one. Or, if the environment has one, this is - called on that function's output for constants. - """ - return str(value) - - _finalize: t.Optional[_FinalizeInfo] = None - - def _make_finalize(self) -> _FinalizeInfo: - """Build the finalize function to be used on constants and at - runtime. Cached so it's only created once for all output nodes. - - Returns a ``namedtuple`` with the following attributes: - - ``const`` - A function to finalize constant data at compile time. - - ``src`` - Source code to output around nodes to be evaluated at - runtime. - """ - if self._finalize is not None: - return self._finalize - - finalize: t.Optional[t.Callable[..., t.Any]] - finalize = default = self._default_finalize - src = None - - if self.environment.finalize: - src = "environment.finalize(" - env_finalize = self.environment.finalize - pass_arg = { - _PassArg.context: "context", - _PassArg.eval_context: "context.eval_ctx", - _PassArg.environment: "environment", - }.get( - _PassArg.from_obj(env_finalize) # type: ignore - ) - finalize = None - - if pass_arg is None: - - def finalize(value: t.Any) -> t.Any: # noqa: F811 - return default(env_finalize(value)) - - else: - src = f"{src}{pass_arg}, " - - if pass_arg == "environment": - - def finalize(value: t.Any) -> t.Any: # noqa: F811 - return default(env_finalize(self.environment, value)) - - self._finalize = self._FinalizeInfo(finalize, src) - return self._finalize - - def _output_const_repr(self, group: t.Iterable[t.Any]) -> str: - """Given a group of constant values converted from ``Output`` - child nodes, produce a string to write to the template module - source. - """ - return repr(concat(group)) - - def _output_child_to_const( - self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo - ) -> str: - """Try to optimize a child of an ``Output`` node by trying to - convert it to constant, finalized data at compile time. - - If :exc:`Impossible` is raised, the node is not constant and - will be evaluated at runtime. Any other exception will also be - evaluated at runtime for easier debugging. - """ - const = node.as_const(frame.eval_ctx) - - if frame.eval_ctx.autoescape: - const = escape(const) - - # Template data doesn't go through finalize. - if isinstance(node, nodes.TemplateData): - return str(const) - - return finalize.const(const) # type: ignore - - def _output_child_pre( - self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo - ) -> None: - """Output extra source code before visiting a child of an - ``Output`` node. - """ - if frame.eval_ctx.volatile: - self.write("(escape if context.eval_ctx.autoescape else str)(") - elif frame.eval_ctx.autoescape: - self.write("escape(") - else: - self.write("str(") - - if finalize.src is not None: - self.write(finalize.src) - - def _output_child_post( - self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo - ) -> None: - """Output extra source code after visiting a child of an - ``Output`` node. - """ - self.write(")") - - if finalize.src is not None: - self.write(")") - - def visit_Output(self, node: nodes.Output, frame: Frame) -> None: - # If an extends is active, don't render outside a block. - if frame.require_output_check: - # A top-level extends is known to exist at compile time. - if self.has_known_extends: - return - - self.writeline("if parent_template is None:") - self.indent() - - finalize = self._make_finalize() - body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = [] - - # Evaluate constants at compile time if possible. Each item in - # body will be either a list of static data or a node to be - # evaluated at runtime. - for child in node.nodes: - try: - if not ( - # If the finalize function requires runtime context, - # constants can't be evaluated at compile time. - finalize.const - # Unless it's basic template data that won't be - # finalized anyway. - or isinstance(child, nodes.TemplateData) - ): - raise nodes.Impossible() - - const = self._output_child_to_const(child, frame, finalize) - except (nodes.Impossible, Exception): - # The node was not constant and needs to be evaluated at - # runtime. Or another error was raised, which is easier - # to debug at runtime. - body.append(child) - continue - - if body and isinstance(body[-1], list): - body[-1].append(const) - else: - body.append([const]) - - if frame.buffer is not None: - if len(body) == 1: - self.writeline(f"{frame.buffer}.append(") - else: - self.writeline(f"{frame.buffer}.extend((") - - self.indent() - - for item in body: - if isinstance(item, list): - # A group of constant data to join and output. - val = self._output_const_repr(item) - - if frame.buffer is None: - self.writeline("yield " + val) - else: - self.writeline(val + ",") - else: - if frame.buffer is None: - self.writeline("yield ", item) - else: - self.newline(item) - - # A node to be evaluated at runtime. - self._output_child_pre(item, frame, finalize) - self.visit(item, frame) - self._output_child_post(item, frame, finalize) - - if frame.buffer is not None: - self.write(",") - - if frame.buffer is not None: - self.outdent() - self.writeline(")" if len(body) == 1 else "))") - - if frame.require_output_check: - self.outdent() - - def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None: - self.push_assign_tracking() - - # ``a.b`` is allowed for assignment, and is parsed as an NSRef. However, - # it is only valid if it references a Namespace object. Emit a check for - # that for each ref here, before assignment code is emitted. This can't - # be done in visit_NSRef as the ref could be in the middle of a tuple. - seen_refs: t.Set[str] = set() - - for nsref in node.find_all(nodes.NSRef): - if nsref.name in seen_refs: - # Only emit the check for each reference once, in case the same - # ref is used multiple times in a tuple, `ns.a, ns.b = c, d`. - continue - - seen_refs.add(nsref.name) - ref = frame.symbols.ref(nsref.name) - self.writeline(f"if not isinstance({ref}, Namespace):") - self.indent() - self.writeline( - "raise TemplateRuntimeError" - '("cannot assign attribute on non-namespace object")' - ) - self.outdent() - - self.newline(node) - self.visit(node.target, frame) - self.write(" = ") - self.visit(node.node, frame) - self.pop_assign_tracking(frame) - - def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None: - self.push_assign_tracking() - block_frame = frame.inner() - # This is a special case. Since a set block always captures we - # will disable output checks. This way one can use set blocks - # toplevel even in extended templates. - block_frame.require_output_check = False - block_frame.symbols.analyze_node(node) - self.enter_frame(block_frame) - self.buffer(block_frame) - self.blockvisit(node.body, block_frame) - self.newline(node) - self.visit(node.target, frame) - self.write(" = (Markup if context.eval_ctx.autoescape else identity)(") - if node.filter is not None: - self.visit_Filter(node.filter, block_frame) - else: - self.write(f"concat({block_frame.buffer})") - self.write(")") - self.pop_assign_tracking(frame) - self.leave_frame(block_frame) - - # -- Expression Visitors - - def visit_Name(self, node: nodes.Name, frame: Frame) -> None: - if node.ctx == "store" and ( - frame.toplevel or frame.loop_frame or frame.block_frame - ): - if self._assign_stack: - self._assign_stack[-1].add(node.name) - ref = frame.symbols.ref(node.name) - - # If we are looking up a variable we might have to deal with the - # case where it's undefined. We can skip that case if the load - # instruction indicates a parameter which are always defined. - if node.ctx == "load": - load = frame.symbols.find_load(ref) - if not ( - load is not None - and load[0] == VAR_LOAD_PARAMETER - and not self.parameter_is_undeclared(ref) - ): - self.write( - f"(undefined(name={node.name!r}) if {ref} is missing else {ref})" - ) - return - - self.write(ref) - - def visit_NSRef(self, node: nodes.NSRef, frame: Frame) -> None: - # NSRef is a dotted assignment target a.b=c, but uses a[b]=c internally. - # visit_Assign emits code to validate that each ref is to a Namespace - # object only. That can't be emitted here as the ref could be in the - # middle of a tuple assignment. - ref = frame.symbols.ref(node.name) - self.writeline(f"{ref}[{node.attr!r}]") - - def visit_Const(self, node: nodes.Const, frame: Frame) -> None: - val = node.as_const(frame.eval_ctx) - if isinstance(val, float): - self.write(str(val)) - else: - self.write(repr(val)) - - def visit_TemplateData(self, node: nodes.TemplateData, frame: Frame) -> None: - try: - self.write(repr(node.as_const(frame.eval_ctx))) - except nodes.Impossible: - self.write( - f"(Markup if context.eval_ctx.autoescape else identity)({node.data!r})" - ) - - def visit_Tuple(self, node: nodes.Tuple, frame: Frame) -> None: - self.write("(") - idx = -1 - for idx, item in enumerate(node.items): - if idx: - self.write(", ") - self.visit(item, frame) - self.write(",)" if idx == 0 else ")") - - def visit_List(self, node: nodes.List, frame: Frame) -> None: - self.write("[") - for idx, item in enumerate(node.items): - if idx: - self.write(", ") - self.visit(item, frame) - self.write("]") - - def visit_Dict(self, node: nodes.Dict, frame: Frame) -> None: - self.write("{") - for idx, item in enumerate(node.items): - if idx: - self.write(", ") - self.visit(item.key, frame) - self.write(": ") - self.visit(item.value, frame) - self.write("}") - - visit_Add = _make_binop("+") - visit_Sub = _make_binop("-") - visit_Mul = _make_binop("*") - visit_Div = _make_binop("/") - visit_FloorDiv = _make_binop("//") - visit_Pow = _make_binop("**") - visit_Mod = _make_binop("%") - visit_And = _make_binop("and") - visit_Or = _make_binop("or") - visit_Pos = _make_unop("+") - visit_Neg = _make_unop("-") - visit_Not = _make_unop("not ") - - @optimizeconst - def visit_Concat(self, node: nodes.Concat, frame: Frame) -> None: - if frame.eval_ctx.volatile: - func_name = "(markup_join if context.eval_ctx.volatile else str_join)" - elif frame.eval_ctx.autoescape: - func_name = "markup_join" - else: - func_name = "str_join" - self.write(f"{func_name}((") - for arg in node.nodes: - self.visit(arg, frame) - self.write(", ") - self.write("))") - - @optimizeconst - def visit_Compare(self, node: nodes.Compare, frame: Frame) -> None: - self.write("(") - self.visit(node.expr, frame) - for op in node.ops: - self.visit(op, frame) - self.write(")") - - def visit_Operand(self, node: nodes.Operand, frame: Frame) -> None: - self.write(f" {operators[node.op]} ") - self.visit(node.expr, frame) - - @optimizeconst - def visit_Getattr(self, node: nodes.Getattr, frame: Frame) -> None: - if self.environment.is_async: - self.write("(await auto_await(") - - self.write("environment.getattr(") - self.visit(node.node, frame) - self.write(f", {node.attr!r})") - - if self.environment.is_async: - self.write("))") - - @optimizeconst - def visit_Getitem(self, node: nodes.Getitem, frame: Frame) -> None: - # slices bypass the environment getitem method. - if isinstance(node.arg, nodes.Slice): - self.visit(node.node, frame) - self.write("[") - self.visit(node.arg, frame) - self.write("]") - else: - if self.environment.is_async: - self.write("(await auto_await(") - - self.write("environment.getitem(") - self.visit(node.node, frame) - self.write(", ") - self.visit(node.arg, frame) - self.write(")") - - if self.environment.is_async: - self.write("))") - - def visit_Slice(self, node: nodes.Slice, frame: Frame) -> None: - if node.start is not None: - self.visit(node.start, frame) - self.write(":") - if node.stop is not None: - self.visit(node.stop, frame) - if node.step is not None: - self.write(":") - self.visit(node.step, frame) - - @contextmanager - def _filter_test_common( - self, node: t.Union[nodes.Filter, nodes.Test], frame: Frame, is_filter: bool - ) -> t.Iterator[None]: - if self.environment.is_async: - self.write("(await auto_await(") - - if is_filter: - self.write(f"{self.filters[node.name]}(") - func = self.environment.filters.get(node.name) - else: - self.write(f"{self.tests[node.name]}(") - func = self.environment.tests.get(node.name) - - # When inside an If or CondExpr frame, allow the filter to be - # undefined at compile time and only raise an error if it's - # actually called at runtime. See pull_dependencies. - if func is None and not frame.soft_frame: - type_name = "filter" if is_filter else "test" - self.fail(f"No {type_name} named {node.name!r}.", node.lineno) - - pass_arg = { - _PassArg.context: "context", - _PassArg.eval_context: "context.eval_ctx", - _PassArg.environment: "environment", - }.get( - _PassArg.from_obj(func) # type: ignore - ) - - if pass_arg is not None: - self.write(f"{pass_arg}, ") - - # Back to the visitor function to handle visiting the target of - # the filter or test. - yield - - self.signature(node, frame) - self.write(")") - - if self.environment.is_async: - self.write("))") - - @optimizeconst - def visit_Filter(self, node: nodes.Filter, frame: Frame) -> None: - with self._filter_test_common(node, frame, True): - # if the filter node is None we are inside a filter block - # and want to write to the current buffer - if node.node is not None: - self.visit(node.node, frame) - elif frame.eval_ctx.volatile: - self.write( - f"(Markup(concat({frame.buffer}))" - f" if context.eval_ctx.autoescape else concat({frame.buffer}))" - ) - elif frame.eval_ctx.autoescape: - self.write(f"Markup(concat({frame.buffer}))") - else: - self.write(f"concat({frame.buffer})") - - @optimizeconst - def visit_Test(self, node: nodes.Test, frame: Frame) -> None: - with self._filter_test_common(node, frame, False): - self.visit(node.node, frame) - - @optimizeconst - def visit_CondExpr(self, node: nodes.CondExpr, frame: Frame) -> None: - frame = frame.soft() - - def write_expr2() -> None: - if node.expr2 is not None: - self.visit(node.expr2, frame) - return - - self.write( - f'cond_expr_undefined("the inline if-expression on' - f" {self.position(node)} evaluated to false and no else" - f' section was defined.")' - ) - - self.write("(") - self.visit(node.expr1, frame) - self.write(" if ") - self.visit(node.test, frame) - self.write(" else ") - write_expr2() - self.write(")") - - @optimizeconst - def visit_Call( - self, node: nodes.Call, frame: Frame, forward_caller: bool = False - ) -> None: - if self.environment.is_async: - self.write("(await auto_await(") - if self.environment.sandboxed: - self.write("environment.call(context, ") - else: - self.write("context.call(") - self.visit(node.node, frame) - extra_kwargs = {"caller": "caller"} if forward_caller else None - loop_kwargs = {"_loop_vars": "_loop_vars"} if frame.loop_frame else {} - block_kwargs = {"_block_vars": "_block_vars"} if frame.block_frame else {} - if extra_kwargs: - extra_kwargs.update(loop_kwargs, **block_kwargs) - elif loop_kwargs or block_kwargs: - extra_kwargs = dict(loop_kwargs, **block_kwargs) - self.signature(node, frame, extra_kwargs) - self.write(")") - if self.environment.is_async: - self.write("))") - - def visit_Keyword(self, node: nodes.Keyword, frame: Frame) -> None: - self.write(node.key + "=") - self.visit(node.value, frame) - - # -- Unused nodes for extensions - - def visit_MarkSafe(self, node: nodes.MarkSafe, frame: Frame) -> None: - self.write("Markup(") - self.visit(node.expr, frame) - self.write(")") - - def visit_MarkSafeIfAutoescape( - self, node: nodes.MarkSafeIfAutoescape, frame: Frame - ) -> None: - self.write("(Markup if context.eval_ctx.autoescape else identity)(") - self.visit(node.expr, frame) - self.write(")") - - def visit_EnvironmentAttribute( - self, node: nodes.EnvironmentAttribute, frame: Frame - ) -> None: - self.write("environment." + node.name) - - def visit_ExtensionAttribute( - self, node: nodes.ExtensionAttribute, frame: Frame - ) -> None: - self.write(f"environment.extensions[{node.identifier!r}].{node.name}") - - def visit_ImportedName(self, node: nodes.ImportedName, frame: Frame) -> None: - self.write(self.import_aliases[node.importname]) - - def visit_InternalName(self, node: nodes.InternalName, frame: Frame) -> None: - self.write(node.name) - - def visit_ContextReference( - self, node: nodes.ContextReference, frame: Frame - ) -> None: - self.write("context") - - def visit_DerivedContextReference( - self, node: nodes.DerivedContextReference, frame: Frame - ) -> None: - self.write(self.derive_context(frame)) - - def visit_Continue(self, node: nodes.Continue, frame: Frame) -> None: - self.writeline("continue", node) - - def visit_Break(self, node: nodes.Break, frame: Frame) -> None: - self.writeline("break", node) - - def visit_Scope(self, node: nodes.Scope, frame: Frame) -> None: - scope_frame = frame.inner() - scope_frame.symbols.analyze_node(node) - self.enter_frame(scope_frame) - self.blockvisit(node.body, scope_frame) - self.leave_frame(scope_frame) - - def visit_OverlayScope(self, node: nodes.OverlayScope, frame: Frame) -> None: - ctx = self.temporary_identifier() - self.writeline(f"{ctx} = {self.derive_context(frame)}") - self.writeline(f"{ctx}.vars = ") - self.visit(node.context, frame) - self.push_context_reference(ctx) - - scope_frame = frame.inner(isolated=True) - scope_frame.symbols.analyze_node(node) - self.enter_frame(scope_frame) - self.blockvisit(node.body, scope_frame) - self.leave_frame(scope_frame) - self.pop_context_reference() - - def visit_EvalContextModifier( - self, node: nodes.EvalContextModifier, frame: Frame - ) -> None: - for keyword in node.options: - self.writeline(f"context.eval_ctx.{keyword.key} = ") - self.visit(keyword.value, frame) - try: - val = keyword.value.as_const(frame.eval_ctx) - except nodes.Impossible: - frame.eval_ctx.volatile = True - else: - setattr(frame.eval_ctx, keyword.key, val) - - def visit_ScopedEvalContextModifier( - self, node: nodes.ScopedEvalContextModifier, frame: Frame - ) -> None: - old_ctx_name = self.temporary_identifier() - saved_ctx = frame.eval_ctx.save() - self.writeline(f"{old_ctx_name} = context.eval_ctx.save()") - self.visit_EvalContextModifier(node, frame) - for child in node.body: - self.visit(child, frame) - frame.eval_ctx.revert(saved_ctx) - self.writeline(f"context.eval_ctx.revert({old_ctx_name})") diff --git a/serverenv/lib/python3.9/site-packages/jinja2/constants.py b/serverenv/lib/python3.9/site-packages/jinja2/constants.py deleted file mode 100644 index 41a1c23..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/constants.py +++ /dev/null @@ -1,20 +0,0 @@ -#: list of lorem ipsum words used by the lipsum() helper function -LOREM_IPSUM_WORDS = """\ -a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at -auctor augue bibendum blandit class commodo condimentum congue consectetuer -consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus -diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend -elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames -faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac -hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum -justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem -luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie -mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non -nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque -penatibus per pharetra phasellus placerat platea porta porttitor posuere -potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus -ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit -sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor -tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices -ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus -viverra volutpat vulputate""" diff --git a/serverenv/lib/python3.9/site-packages/jinja2/debug.py b/serverenv/lib/python3.9/site-packages/jinja2/debug.py deleted file mode 100644 index eeeeee7..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/debug.py +++ /dev/null @@ -1,191 +0,0 @@ -import sys -import typing as t -from types import CodeType -from types import TracebackType - -from .exceptions import TemplateSyntaxError -from .utils import internal_code -from .utils import missing - -if t.TYPE_CHECKING: - from .runtime import Context - - -def rewrite_traceback_stack(source: t.Optional[str] = None) -> BaseException: - """Rewrite the current exception to replace any tracebacks from - within compiled template code with tracebacks that look like they - came from the template source. - - This must be called within an ``except`` block. - - :param source: For ``TemplateSyntaxError``, the original source if - known. - :return: The original exception with the rewritten traceback. - """ - _, exc_value, tb = sys.exc_info() - exc_value = t.cast(BaseException, exc_value) - tb = t.cast(TracebackType, tb) - - if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated: - exc_value.translated = True - exc_value.source = source - # Remove the old traceback, otherwise the frames from the - # compiler still show up. - exc_value.with_traceback(None) - # Outside of runtime, so the frame isn't executing template - # code, but it still needs to point at the template. - tb = fake_traceback( - exc_value, None, exc_value.filename or "", exc_value.lineno - ) - else: - # Skip the frame for the render function. - tb = tb.tb_next - - stack = [] - - # Build the stack of traceback object, replacing any in template - # code with the source file and line information. - while tb is not None: - # Skip frames decorated with @internalcode. These are internal - # calls that aren't useful in template debugging output. - if tb.tb_frame.f_code in internal_code: - tb = tb.tb_next - continue - - template = tb.tb_frame.f_globals.get("__jinja_template__") - - if template is not None: - lineno = template.get_corresponding_lineno(tb.tb_lineno) - fake_tb = fake_traceback(exc_value, tb, template.filename, lineno) - stack.append(fake_tb) - else: - stack.append(tb) - - tb = tb.tb_next - - tb_next = None - - # Assign tb_next in reverse to avoid circular references. - for tb in reversed(stack): - tb.tb_next = tb_next - tb_next = tb - - return exc_value.with_traceback(tb_next) - - -def fake_traceback( # type: ignore - exc_value: BaseException, tb: t.Optional[TracebackType], filename: str, lineno: int -) -> TracebackType: - """Produce a new traceback object that looks like it came from the - template source instead of the compiled code. The filename, line - number, and location name will point to the template, and the local - variables will be the current template context. - - :param exc_value: The original exception to be re-raised to create - the new traceback. - :param tb: The original traceback to get the local variables and - code info from. - :param filename: The template filename. - :param lineno: The line number in the template source. - """ - if tb is not None: - # Replace the real locals with the context that would be - # available at that point in the template. - locals = get_template_locals(tb.tb_frame.f_locals) - locals.pop("__jinja_exception__", None) - else: - locals = {} - - globals = { - "__name__": filename, - "__file__": filename, - "__jinja_exception__": exc_value, - } - # Raise an exception at the correct line number. - code: CodeType = compile( - "\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec" - ) - - # Build a new code object that points to the template file and - # replaces the location with a block name. - location = "template" - - if tb is not None: - function = tb.tb_frame.f_code.co_name - - if function == "root": - location = "top-level template code" - elif function.startswith("block_"): - location = f"block {function[6:]!r}" - - if sys.version_info >= (3, 8): - code = code.replace(co_name=location) - else: - code = CodeType( - code.co_argcount, - code.co_kwonlyargcount, - code.co_nlocals, - code.co_stacksize, - code.co_flags, - code.co_code, - code.co_consts, - code.co_names, - code.co_varnames, - code.co_filename, - location, - code.co_firstlineno, - code.co_lnotab, - code.co_freevars, - code.co_cellvars, - ) - - # Execute the new code, which is guaranteed to raise, and return - # the new traceback without this frame. - try: - exec(code, globals, locals) - except BaseException: - return sys.exc_info()[2].tb_next # type: ignore - - -def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]: - """Based on the runtime locals, get the context that would be - available at that point in the template. - """ - # Start with the current template context. - ctx: t.Optional[Context] = real_locals.get("context") - - if ctx is not None: - data: t.Dict[str, t.Any] = ctx.get_all().copy() - else: - data = {} - - # Might be in a derived context that only sets local variables - # rather than pushing a context. Local variables follow the scheme - # l_depth_name. Find the highest-depth local that has a value for - # each name. - local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {} - - for name, value in real_locals.items(): - if not name.startswith("l_") or value is missing: - # Not a template variable, or no longer relevant. - continue - - try: - _, depth_str, name = name.split("_", 2) - depth = int(depth_str) - except ValueError: - continue - - cur_depth = local_overrides.get(name, (-1,))[0] - - if cur_depth < depth: - local_overrides[name] = (depth, value) - - # Modify the context with any derived context. - for name, (_, value) in local_overrides.items(): - if value is missing: - data.pop(name, None) - else: - data[name] = value - - return data diff --git a/serverenv/lib/python3.9/site-packages/jinja2/defaults.py b/serverenv/lib/python3.9/site-packages/jinja2/defaults.py deleted file mode 100644 index 638cad3..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/defaults.py +++ /dev/null @@ -1,48 +0,0 @@ -import typing as t - -from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401 -from .tests import TESTS as DEFAULT_TESTS # noqa: F401 -from .utils import Cycler -from .utils import generate_lorem_ipsum -from .utils import Joiner -from .utils import Namespace - -if t.TYPE_CHECKING: - import typing_extensions as te - -# defaults for the parser / lexer -BLOCK_START_STRING = "{%" -BLOCK_END_STRING = "%}" -VARIABLE_START_STRING = "{{" -VARIABLE_END_STRING = "}}" -COMMENT_START_STRING = "{#" -COMMENT_END_STRING = "#}" -LINE_STATEMENT_PREFIX: t.Optional[str] = None -LINE_COMMENT_PREFIX: t.Optional[str] = None -TRIM_BLOCKS = False -LSTRIP_BLOCKS = False -NEWLINE_SEQUENCE: "te.Literal['\\n', '\\r\\n', '\\r']" = "\n" -KEEP_TRAILING_NEWLINE = False - -# default filters, tests and namespace - -DEFAULT_NAMESPACE = { - "range": range, - "dict": dict, - "lipsum": generate_lorem_ipsum, - "cycler": Cycler, - "joiner": Joiner, - "namespace": Namespace, -} - -# default policies -DEFAULT_POLICIES: t.Dict[str, t.Any] = { - "compiler.ascii_str": True, - "urlize.rel": "noopener", - "urlize.target": None, - "urlize.extra_schemes": None, - "truncate.leeway": 5, - "json.dumps_function": None, - "json.dumps_kwargs": {"sort_keys": True}, - "ext.i18n.trimmed": False, -} diff --git a/serverenv/lib/python3.9/site-packages/jinja2/environment.py b/serverenv/lib/python3.9/site-packages/jinja2/environment.py deleted file mode 100644 index 0fc6e5b..0000000 --- a/serverenv/lib/python3.9/site-packages/jinja2/environment.py +++ /dev/null @@ -1,1672 +0,0 @@ -"""Classes for managing templates and their runtime and compile time -options. -""" - -import os -import typing -import typing as t -import weakref -from collections import ChainMap -from functools import lru_cache -from functools import partial -from functools import reduce -from types import CodeType - -from markupsafe import Markup - -from . import nodes -from .compiler import CodeGenerator -from .compiler import generate -from .defaults import BLOCK_END_STRING -from .defaults import BLOCK_START_STRING -from .defaults import COMMENT_END_STRING -from .defaults import COMMENT_START_STRING -from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined] -from .defaults import DEFAULT_NAMESPACE -from .defaults import DEFAULT_POLICIES -from .defaults import DEFAULT_TESTS # type: ignore[attr-defined] -from .defaults import KEEP_TRAILING_NEWLINE -from .defaults import LINE_COMMENT_PREFIX -from .defaults import LINE_STATEMENT_PREFIX -from .defaults import LSTRIP_BLOCKS -from .defaults import NEWLINE_SEQUENCE -from .defaults import TRIM_BLOCKS -from .defaults import VARIABLE_END_STRING -from .defaults import VARIABLE_START_STRING -from .exceptions import TemplateNotFound -from .exceptions import TemplateRuntimeError -from .exceptions import TemplatesNotFound -from .exceptions import TemplateSyntaxError -from .exceptions import UndefinedError -from .lexer import get_lexer -from .lexer import Lexer -from .lexer import TokenStream -from .nodes import EvalContext -from .parser import Parser -from .runtime import Context -from .runtime import new_context -from .runtime import Undefined -from .utils import _PassArg -from .utils import concat -from .utils import consume -from .utils import import_string -from .utils import internalcode -from .utils import LRUCache -from .utils import missing - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .bccache import BytecodeCache - from .ext import Extension - from .loaders import BaseLoader - -_env_bound = t.TypeVar("_env_bound", bound="Environment") - - -# for direct template usage we have up to ten living environments -@lru_cache(maxsize=10) -def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: - """Return a new spontaneous environment. A spontaneous environment - is used for templates created directly rather than through an - existing environment. - - :param cls: Environment class to create. - :param args: Positional arguments passed to environment. - """ - env = cls(*args) - env.shared = True - return env - - -def create_cache( - size: int, -) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: - """Return the cache class for the given size.""" - if size == 0: - return None - - if size < 0: - return {} - - return LRUCache(size) # type: ignore - - -def copy_cache( - cache: t.Optional[t.MutableMapping[t.Any, t.Any]], -) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: - """Create an empty copy of the given cache.""" - if cache is None: - return None - - if type(cache) is dict: # noqa E721 - return {} - - return LRUCache(cache.capacity) # type: ignore - - -def load_extensions( - environment: "Environment", - extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], -) -> t.Dict[str, "Extension"]: - """Load the extensions from the list and bind it to the environment. - Returns a dict of instantiated extensions. - """ - result = {} - - for extension in extensions: - if isinstance(extension, str): - extension = t.cast(t.Type["Extension"], import_string(extension)) - - result[extension.identifier] = extension(environment) - - return result - - -def _environment_config_check(environment: _env_bound) -> _env_bound: - """Perform a sanity check on the environment.""" - assert issubclass( - environment.undefined, Undefined - ), "'undefined' must be a subclass of 'jinja2.Undefined'." - assert ( - environment.block_start_string - != environment.variable_start_string - != environment.comment_start_string - ), "block, variable and comment start strings must be different." - assert environment.newline_sequence in { - "\r", - "\r\n", - "\n", - }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'." - return environment - - -class Environment: - r"""The core component of Jinja is the `Environment`. It contains - important shared variables like configuration, filters, tests, - globals and others. Instances of this class may be modified if - they are not shared and if no template was loaded so far. - Modifications on environments after the first template was loaded - will lead to surprising effects and undefined behavior. - - Here are the possible initialization parameters: - - `block_start_string` - The string marking the beginning of a block. Defaults to ``'{%'``. - - `block_end_string` - The string marking the end of a block. Defaults to ``'%}'``. - - `variable_start_string` - The string marking the beginning of a print statement. - Defaults to ``'{{'``. - - `variable_end_string` - The string marking the end of a print statement. Defaults to - ``'}}'``. - - `comment_start_string` - The string marking the beginning of a comment. Defaults to ``'{#'``. - - `comment_end_string` - The string marking the end of a comment. Defaults to ``'#}'``. - - `line_statement_prefix` - If given and a string, this will be used as prefix for line based - statements. See also :ref:`line-statements`. - - `line_comment_prefix` - If given and a string, this will be used as prefix for line based - comments. See also :ref:`line-statements`. - - .. versionadded:: 2.2 - - `trim_blocks` - If this is set to ``True`` the first newline after a block is - removed (block, not variable tag!). Defaults to `False`. - - `lstrip_blocks` - If this is set to ``True`` leading spaces and tabs are stripped - from the start of a line to a block. Defaults to `False`. - - `newline_sequence` - The sequence that starts a newline. Must be one of ``'\r'``, - ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a - useful default for Linux and OS X systems as well as web - applications. - - `keep_trailing_newline` - Preserve the trailing newline when rendering templates. - The default is ``False``, which causes a single newline, - if present, to be stripped from the end of the template. - - .. versionadded:: 2.7 - - `extensions` - List of Jinja extensions to use. This can either be import paths - as strings or extension classes. For more information have a - look at :ref:`the extensions documentation `. - - `optimized` - should the optimizer be enabled? Default is ``True``. - - `undefined` - :class:`Undefined` or a subclass of it that is used to represent - undefined values in the template. - - `finalize` - A callable that can be used to process the result of a variable - expression before it is output. For example one can convert - ``None`` implicitly into an empty string here. - - `autoescape` - If set to ``True`` the XML/HTML autoescaping feature is enabled by - default. For more details about autoescaping see - :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also - be a callable that is passed the template name and has to - return ``True`` or ``False`` depending on autoescape should be - enabled by default. - - .. versionchanged:: 2.4 - `autoescape` can now be a function - - `loader` - The template loader for this environment. - - `cache_size` - The size of the cache. Per default this is ``400`` which means - that if more than 400 templates are loaded the loader will clean - out the least recently used template. If the cache size is set to - ``0`` templates are recompiled all the time, if the cache size is - ``-1`` the cache will not be cleaned. - - .. versionchanged:: 2.8 - The cache size was increased to 400 from a low 50. - - `auto_reload` - Some loaders load templates from locations where the template - sources may change (ie: file system or database). If - ``auto_reload`` is set to ``True`` (default) every time a template is - requested the loader checks if the source changed and if yes, it - will reload the template. For higher performance it's possible to - disable that. - - `bytecode_cache` - If set to a bytecode cache object, this object will provide a - cache for the internal Jinja bytecode so that templates don't - have to be parsed if they were not changed. - - See :ref:`bytecode-cache` for more information. - - `enable_async` - If set to true this enables async template execution which - allows using async functions and generators. - """ - - #: if this environment is sandboxed. Modifying this variable won't make - #: the environment sandboxed though. For a real sandboxed environment - #: have a look at jinja2.sandbox. This flag alone controls the code - #: generation by the compiler. - sandboxed = False - - #: True if the environment is just an overlay - overlayed = False - - #: the environment this environment is linked to if it is an overlay - linked_to: t.Optional["Environment"] = None - - #: shared environments have this set to `True`. A shared environment - #: must not be modified - shared = False - - #: the class that is used for code generation. See - #: :class:`~jinja2.compiler.CodeGenerator` for more information. - code_generator_class: t.Type["CodeGenerator"] = CodeGenerator - - concat = "".join - - #: the context class that is used for templates. See - #: :class:`~jinja2.runtime.Context` for more information. - context_class: t.Type[Context] = Context - - template_class: t.Type["Template"] - - def __init__( - self, - block_start_string: str = BLOCK_START_STRING, - block_end_string: str = BLOCK_END_STRING, - variable_start_string: str = VARIABLE_START_STRING, - variable_end_string: str = VARIABLE_END_STRING, - comment_start_string: str = COMMENT_START_STRING, - comment_end_string: str = COMMENT_END_STRING, - line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, - line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, - trim_blocks: bool = TRIM_BLOCKS, - lstrip_blocks: bool = LSTRIP_BLOCKS, - newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, - keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, - extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), - optimized: bool = True, - undefined: t.Type[Undefined] = Undefined, - finalize: t.Optional[t.Callable[..., t.Any]] = None, - autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, - loader: t.Optional["BaseLoader"] = None, - cache_size: int = 400, - auto_reload: bool = True, - bytecode_cache: t.Optional["BytecodeCache"] = None, - enable_async: bool = False, - ): - # !!Important notice!! - # The constructor accepts quite a few arguments that should be - # passed by keyword rather than position. However it's important to - # not change the order of arguments because it's used at least - # internally in those cases: - # - spontaneous environments (i18n extension and Template) - # - unittests - # If parameter changes are required only add parameters at the end - # and don't change the arguments (or the defaults!) of the arguments - # existing already. - - # lexer / parser information - self.block_start_string = block_start_string - self.block_end_string = block_end_string - self.variable_start_string = variable_start_string - self.variable_end_string = variable_end_string - self.comment_start_string = comment_start_string - self.comment_end_string = comment_end_string - self.line_statement_prefix = line_statement_prefix - self.line_comment_prefix = line_comment_prefix - self.trim_blocks = trim_blocks - self.lstrip_blocks = lstrip_blocks - self.newline_sequence = newline_sequence - self.keep_trailing_newline = keep_trailing_newline - - # runtime information - self.undefined: t.Type[Undefined] = undefined - self.optimized = optimized - self.finalize = finalize - self.autoescape = autoescape - - # defaults - self.filters = DEFAULT_FILTERS.copy() - self.tests = DEFAULT_TESTS.copy() - self.globals = DEFAULT_NAMESPACE.copy() - - # set the loader provided - self.loader = loader - self.cache = create_cache(cache_size) - self.bytecode_cache = bytecode_cache - self.auto_reload = auto_reload - - # configurable policies - self.policies = DEFAULT_POLICIES.copy() - - # load extensions - self.extensions = load_extensions(self, extensions) - - self.is_async = enable_async - _environment_config_check(self) - - def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None: - """Adds an extension after the environment was created. - - .. versionadded:: 2.5 - """ - self.extensions.update(load_extensions(self, [extension])) - - def extend(self, **attributes: t.Any) -> None: - """Add the items to the instance of the environment if they do not exist - yet. This is used by :ref:`extensions ` to register - callbacks and configuration values without breaking inheritance. - """ - for key, value in attributes.items(): - if not hasattr(self, key): - setattr(self, key, value) - - def overlay( - self, - block_start_string: str = missing, - block_end_string: str = missing, - variable_start_string: str = missing, - variable_end_string: str = missing, - comment_start_string: str = missing, - comment_end_string: str = missing, - line_statement_prefix: t.Optional[str] = missing, - line_comment_prefix: t.Optional[str] = missing, - trim_blocks: bool = missing, - lstrip_blocks: bool = missing, - newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing, - keep_trailing_newline: bool = missing, - extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing, - optimized: bool = missing, - undefined: t.Type[Undefined] = missing, - finalize: t.Optional[t.Callable[..., t.Any]] = missing, - autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing, - loader: t.Optional["BaseLoader"] = missing, - cache_size: int = missing, - auto_reload: bool = missing, - bytecode_cache: t.Optional["BytecodeCache"] = missing, - enable_async: bool = missing, - ) -> "te.Self": - """Create a new overlay environment that shares all the data with the - current environment except for cache and the overridden attributes. - Extensions cannot be removed for an overlayed environment. An overlayed - environment automatically gets all the extensions of the environment it - is linked to plus optional extra extensions. - - Creating overlays should happen after the initial environment was set - up completely. Not all attributes are truly linked, some are just - copied over so modifications on the original environment may not shine - through. - - .. versionchanged:: 3.1.5 - ``enable_async`` is applied correctly. - - .. versionchanged:: 3.1.2 - Added the ``newline_sequence``, ``keep_trailing_newline``, - and ``enable_async`` parameters to match ``__init__``. - """ - args = dict(locals()) - del args["self"], args["cache_size"], args["extensions"], args["enable_async"] - - rv = object.__new__(self.__class__) - rv.__dict__.update(self.__dict__) - rv.overlayed = True - rv.linked_to = self - - for key, value in args.items(): - if value is not missing: - setattr(rv, key, value) - - if cache_size is not missing: - rv.cache = create_cache(cache_size) - else: - rv.cache = copy_cache(self.cache) - - rv.extensions = {} - for key, value in self.extensions.items(): - rv.extensions[key] = value.bind(rv) - if extensions is not missing: - rv.extensions.update(load_extensions(rv, extensions)) - - if enable_async is not missing: - rv.is_async = enable_async - - return _environment_config_check(rv) - - @property - def lexer(self) -> Lexer: - """The lexer for this environment.""" - return get_lexer(self) - - def iter_extensions(self) -> t.Iterator["Extension"]: - """Iterates over the extensions by priority.""" - return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) - - def getitem( - self, obj: t.Any, argument: t.Union[str, t.Any] - ) -> t.Union[t.Any, Undefined]: - """Get an item or attribute of an object but prefer the item.""" - try: - return obj[argument] - except (AttributeError, TypeError, LookupError): - if isinstance(argument, str): - try: - attr = str(argument) - except Exception: - pass - else: - try: - return getattr(obj, attr) - except AttributeError: - pass - return self.undefined(obj=obj, name=argument) - - def getattr(self, obj: t.Any, attribute: str) -> t.Any: - """Get an item or attribute of an object but prefer the attribute. - Unlike :meth:`getitem` the attribute *must* be a string. - """ - try: - return getattr(obj, attribute) - except AttributeError: - pass - try: - return obj[attribute] - except (TypeError, LookupError, AttributeError): - return self.undefined(obj=obj, name=attribute) - - def _filter_test_common( - self, - name: t.Union[str, Undefined], - value: t.Any, - args: t.Optional[t.Sequence[t.Any]], - kwargs: t.Optional[t.Mapping[str, t.Any]], - context: t.Optional[Context], - eval_ctx: t.Optional[EvalContext], - is_filter: bool, - ) -> t.Any: - if is_filter: - env_map = self.filters - type_name = "filter" - else: - env_map = self.tests - type_name = "test" - - func = env_map.get(name) # type: ignore - - if func is None: - msg = f"No {type_name} named {name!r}." - - if isinstance(name, Undefined): - try: - name._fail_with_undefined_error() - except Exception as e: - msg = f"{msg} ({e}; did you forget to quote the callable name?)" - - raise TemplateRuntimeError(msg) - - args = [value, *(args if args is not None else ())] - kwargs = kwargs if kwargs is not None else {} - pass_arg = _PassArg.from_obj(func) - - if pass_arg is _PassArg.context: - if context is None: - raise TemplateRuntimeError( - f"Attempted to invoke a context {type_name} without context." - ) - - args.insert(0, context) - elif pass_arg is _PassArg.eval_context: - if eval_ctx is None: - if context is not None: - eval_ctx = context.eval_ctx - else: - eval_ctx = EvalContext(self) - - args.insert(0, eval_ctx) - elif pass_arg is _PassArg.environment: - args.insert(0, self) - - return func(*args, **kwargs) - - def call_filter( - self, - name: str, - value: t.Any, - args: t.Optional[t.Sequence[t.Any]] = None, - kwargs: t.Optional[t.Mapping[str, t.Any]] = None, - context: t.Optional[Context] = None, - eval_ctx: t.Optional[EvalContext] = None, - ) -> t.Any: - """Invoke a filter on a value the same way the compiler does. - - This might return a coroutine if the filter is running from an - environment in async mode and the filter supports async - execution. It's your responsibility to await this if needed. - - .. versionadded:: 2.7 - """ - return self._filter_test_common( - name, value, args, kwargs, context, eval_ctx, True - ) - - def call_test( - self, - name: str, - value: t.Any, - args: t.Optional[t.Sequence[t.Any]] = None, - kwargs: t.Optional[t.Mapping[str, t.Any]] = None, - context: t.Optional[Context] = None, - eval_ctx: t.Optional[EvalContext] = None, - ) -> t.Any: - """Invoke a test on a value the same way the compiler does. - - This might return a coroutine if the test is running from an - environment in async mode and the test supports async execution. - It's your responsibility to await this if needed. - - .. versionchanged:: 3.0 - Tests support ``@pass_context``, etc. decorators. Added - the ``context`` and ``eval_ctx`` parameters. - - .. versionadded:: 2.7 - """ - return self._filter_test_common( - name, value, args, kwargs, context, eval_ctx, False - ) - - @internalcode - def parse( - self, - source: str, - name: t.Optional[str] = None, - filename: t.Optional[str] = None, - ) -> nodes.Template: - """Parse the sourcecode and return the abstract syntax tree. This - tree of nodes is used by the compiler to convert the template into - executable source- or bytecode. This is useful for debugging or to - extract information from templates. - - If you are :ref:`developing Jinja extensions ` - this gives you a good overview of the node tree generated. - """ - try: - return self._parse(source, name, filename) - except TemplateSyntaxError: - self.handle_exception(source=source) - - def _parse( - self, source: str, name: t.Optional[str], filename: t.Optional[str] - ) -> nodes.Template: - """Internal parsing function used by `parse` and `compile`.""" - return Parser(self, source, name, filename).parse() - - def lex( - self, - source: str, - name: t.Optional[str] = None, - filename: t.Optional[str] = None, - ) -> t.Iterator[t.Tuple[int, str, str]]: - """Lex the given sourcecode and return a generator that yields - tokens as tuples in the form ``(lineno, token_type, value)``. - This can be useful for :ref:`extension development ` - and debugging templates. - - This does not perform preprocessing. If you want the preprocessing - of the extensions to be applied you have to filter source through - the :meth:`preprocess` method. - """ - source = str(source) - try: - return self.lexer.tokeniter(source, name, filename) - except TemplateSyntaxError: - self.handle_exception(source=source) - - def preprocess( - self, - source: str, - name: t.Optional[str] = None, - filename: t.Optional[str] = None, - ) -> str: - """Preprocesses the source with all extensions. This is automatically - called for all parsing and compiling methods but *not* for :meth:`lex` - because there you usually only want the actual source tokenized. - """ - return reduce( - lambda s, e: e.preprocess(s, name, filename), - self.iter_extensions(), - str(source), - ) - - def _tokenize( - self, - source: str, - name: t.Optional[str], - filename: t.Optional[str] = None, - state: t.Optional[str] = None, - ) -> TokenStream: - """Called by the parser to do the preprocessing and filtering - for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. - """ - source = self.preprocess(source, name, filename) - stream = self.lexer.tokenize(source, name, filename, state) - - for ext in self.iter_extensions(): - stream = ext.filter_stream(stream) # type: ignore - - if not isinstance(stream, TokenStream): - stream = TokenStream(stream, name, filename) - - return stream - - def _generate( - self, - source: nodes.Template, - name: t.Optional[str], - filename: t.Optional[str], - defer_init: bool = False, - ) -> str: - """Internal hook that can be overridden to hook a different generate - method in. - - .. versionadded:: 2.5 - """ - return generate( # type: ignore - source, - self, - name, - filename, - defer_init=defer_init, - optimized=self.optimized, - ) - - def _compile(self, source: str, filename: str) -> CodeType: - """Internal hook that can be overridden to hook a different compile - method in. - - .. versionadded:: 2.5 - """ - return compile(source, filename, "exec") - - @typing.overload - def compile( - self, - source: t.Union[str, nodes.Template], - name: t.Optional[str] = None, - filename: t.Optional[str] = None, - raw: "te.Literal[False]" = False, - defer_init: bool = False, - ) -> CodeType: ... - - @typing.overload - def compile( - self, - source: t.Union[str, nodes.Template], - name: t.Optional[str] = None, - filename: t.Optional[str] = None, - raw: "te.Literal[True]" = ..., - defer_init: bool = False, - ) -> str: ... - - @internalcode - def compile( - self, - source: t.Union[str, nodes.Template], - name: t.Optional[str] = None, - filename: t.Optional[str] = None, - raw: bool = False, - defer_init: bool = False, - ) -> t.Union[str, CodeType]: - """Compile a node or template source code. The `name` parameter is - the load name of the template after it was joined using - :meth:`join_path` if necessary, not the filename on the file system. - the `filename` parameter is the estimated filename of the template on - the file system. If the template came from a database or memory this - can be omitted. - - The return value of this method is a python code object. If the `raw` - parameter is `True` the return value will be a string with python - code equivalent to the bytecode returned otherwise. This method is - mainly used internally. - - `defer_init` is use internally to aid the module code generator. This - causes the generated code to be able to import without the global - environment variable to be set. - - .. versionadded:: 2.4 - `defer_init` parameter added. - """ - source_hint = None - try: - if isinstance(source, str): - source_hint = source - source = self._parse(source, name, filename) - source = self._generate(source, name, filename, defer_init=defer_init) - if raw: - return source - if filename is None: - filename = "